U
Angew が提供する回答は正しいアプローチを示していますが、と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
}