6

次のクラスがあるとします。

template <class T, class U, class V> Foo
{
    ...
};

テンプレート パラメーターには明確なマッピングがあるため、T に基づいて他のテンプレート引数 U と V を推測できます。たとえば、T が double の場合、U と V は常にクラス D1 と D2 になり、T が float の場合、U と V は常に他のクラス F1 と F2 になります。

それを念頭に置いて、テンプレート引数を 1 つだけ渡し、コンパイラーに他の 2 つのパラメーターを推測させる方法はありますか?

簡単な答えは、これらの他のクラスもテンプレート化してテンプレート引数 T を渡すことですが、これらのクラスをテンプレート化することはできません (ツールによって自動生成されます)。

理想的には、次のように typedef または #define を使用できます。

typedef Foo<double> Foo<double, D1, D2>
typedef Foo<float> Foo<float, F1, F2>

ただし、これらはコンパイルされません。この問題を解決するためにテンプレート メタプログラミングまたはテンプレート テンプレート パラメーターを使用する方法があるかどうか疑問に思っていますが、それらの概念を理解することはできず、おそらくもっと簡単な答えがあると直感しています。誰にもアイデアはありますか?

4

2 に答える 2

6

次のように、Uおよびを取り除くことができます。V

template <typename T>
struct Foo
{
  typedef typename deduce_from<T>::U U;
  typedef typename deduce_from<T>::V V;
};

ここでdeduce_from、控除プロセスをカプセル化します。

于 2013-02-22T13:53:21.253 に答える
6

UAngew が提供する回答は正しいアプローチを示していますが、とVを推測できず、インスタンス化するクライアントによって提供されなければならない状況に対処する方法は示していません。

このケースを処理するには、テンプレート パラメーターUとに既定の引数を割り当てることができVます。

struct D1 { }; struct D2 { };
struct F1 { }; struct F2 { };

// Primary template
template<typename T>
struct deduce_from
{
};

// Specialization for double: U -> D1, V -> D2
template<>
struct deduce_from<double>
{
    typedef D1 U;
    typedef D2 V;
};

// Specialization for float: U -> F1, V -> F2
template<>
struct deduce_from<float>
{
    typedef F1 U;
    typedef F2 V;
};

// Give defaults to U and V: if deduce_from is not specialized for
// the supplied T, and U or V are not explicitly provided, a compilation
// error will occur 
template<
    typename T,
    typename U = typename deduce_from<T>::U,
    typename V = typename deduce_from<T>::V
    >
struct Foo
{
    typedef U typeU;
    typedef V typeV;
};

上記のソリューションの正しさをテストするための簡単なプログラムを次に示します。

#include <type_traits>

int main()
{
    static_assert(std::is_same<Foo<double>::typeU, D1>::value, "Error!");
    static_assert(std::is_same<Foo<double>::typeV, D2>::value, "Error!");
    static_assert(std::is_same<Foo<float>::typeU, F1>::value, "Error!");
    static_assert(std::is_same<Foo<float>::typeV, F2>::value, "Error!");

    // Uncommenting this will give you an ERROR! 
    // No deduced types for U and V when T is int
    /* static_assert(
        std::is_same<Foo<int>::typeU, void>::value, "Error!"
        ); */
    static_assert(
        std::is_same<Foo<int, bool, char>::typeU, bool>::value, "Error!"
        ); // OK
    static_assert(
        std::is_same<Foo<int, bool, char>::typeV, char>::value, "Error!"
        ); // OK
}
于 2013-02-22T14:09:20.220 に答える