2

以下のコードでは、テンプレート引数がテンプレートの場合、クラス テンプレートは 1 つのパラメーターを使用しますが、関数テンプレートは 2 つを使用します。これは、型推論を使用する場合は問題ありませんが、明示的なテンプレートのインスタンス化を使用する場合は奇妙です。

テンプレート テンプレート パラメータを 1 つのパラメータとして記述することは可能ですか?

この質問は、関数オーバーロード マッチング テンプレート テンプレートにリンクされています

#include <iostream>

template <typename T>
struct C
{
    C (T i)
    {
        std::cout << "simple" << std::endl;
    }
};
template <template<typename TT> class FF, typename TT>
struct C <FF<TT> >          // (1)
{
    C (FF<TT> i)
    {
        std::cout << "template" << std::endl;
    }
};
template <typename T>
void F (T i)
{
    std::cout << "simple" << std::endl;
}

// two template arguments FF and TT.
// Anyway to write this so that the argument count is one?
template <template<typename TT> class FF, typename TT>
void F (FF<TT> i)
{
    std::cout << "template" << std::endl;
}

template <typename T>
struct R
{
    T x;
};
int main()
{
        R<int>     r;
        C<R<int> >{r};      // prints 'template', as expected
        F<R<int> >(r);      // prints 'simple',  probably not what you think
        F<R,int  >(r);      // prints 'template' as expected but 
}

編集:

1 つのパラメーター構文がある場合、オーバーロードの解決で間違った関数が選択されるため、この質問は適切ではないという結論に達しました。これは私には驚きですが、これを証明するコードは次のとおりです (変更された 1 つのテンプレート関数のオーバーロードを除いて、以前と同じコード)。

EDIT2: 明示的なテンプレートの指定をスキップして、メインにさらに印刷を追加しました。

EDIT3: 以下のコードはナンセンスです。@DyPが正しく指摘したように、私は間違いを犯しました。私はvoid F(R<R<T>>)明示的なケースで呼び出していますが、 ではありませんvoid F(R<T>)

#include <iostream>

template <typename T>
struct R
{
    T x;
};
template <typename T>
struct C
{
    C (T i)
    {
        std::cout << "simple" << std::endl;
    }
};
template <template<typename TT> class FF, typename TT>
struct C <FF<TT> >          // (1)
{
    C (FF<TT> i)
    {
        std::cout << "template" << std::endl;
    }
};
template <typename T>
void F (R<T> i)
{
    std::cout << "template" << i.x << std::endl;
}
template <typename T>
void F (T i)
{
    std::cout << "simple" << std::endl;
}
int main()
{
        R<int>     r;
        C<R<int> >{r};      // prints 'template', as expected
        F<R<int> >(r);      // prints 'simple',  probably not the expected overload
        F         (r);      // prints 'template', now overload resolution works. Strange.
}
4

2 に答える 2

1

SFINAE の場合:

#include <type_traits>

template<class T>
struct is_template_with_one_param
: std::false_type
{};

template<template<class> class TT, class T>
struct is_template_with_one_param< TT<T> >
: std::true_type
{};


#include <iostream>

template <typename T>
typename std::enable_if< not is_template_with_one_param<T>{}, void >::type
F (T i)
{
    std::cout << "simple" << std::endl;
}

template <typename T>
typename std::enable_if< is_template_with_one_param<T>{}, void >::type
F (T i)
{
    std::cout << "template" << std::endl;
}

使用例:

template <typename T>
struct R
{
    T x;
};
int main()
{
        F(R<int>{});
        F(42);
}

または、 Jarod42提案を検討してください。

于 2013-10-03T16:29:43.540 に答える
0

別の可能な解決策:

#include <iostream>

template <typename T>
struct C
{
    C (T i)
    {
        std::cout << "simple" << std::endl;
    }
};
template <template<typename TT> class FF, typename TT>
struct C <FF<TT> >          // (1)
{
    C (FF<TT> i)
    {
        std::cout << "template" << std::endl;
    }
};

template <typename T>
void F (T i)
{
    C<T> x(i);
}

template <typename T>
struct R
{
    T x;
};
int main()
{
        R<int>     r;
        F(r);
        F(4);
}
于 2013-10-03T16:40:37.757 に答える