有効な POD であるタイプが必要ですが、その中にどのタイプがどのように含まれているかを指定できるようにしたいと考えています。次に例を示します。
template<Args...>
struct POD
{
//here I would like to create depending on Args appropriate types as a members.
};
C++0x のこの新しい可変個引数テンプレート機能でそれを行うことは可能ですか?
あなたは知っていstd::tuple
ますか?
私の知る限り、すべてのメンバーが POD である場合、それは POD です。私が間違っている場合、それは不可能だと思います。
C++0x 可変個引数テンプレート機能をまだ使用したことがありませんが、次のコードは G++ 4.5 でコンパイルされます。
template <typename... Args>
struct tuple;
template <typename T, typename... Args>
struct tuple<T, Args...> {
T value;
tuple<Args...> inner;
};
template <typename T>
struct tuple<T> {
T value;
};
しかし、内部の値をネストする必要があるため、それらを初期化するのは奇妙です:
int main() {
tuple<int> n1 = { 23 };
tuple<int, float> n2 = { 42, { 0.5f } };
tuple<std::string, double, int> n3 = { "hello, world", { 3.14, { 97 } } };
}
もちろん、値を取得するのは少し面倒です。最も簡単な方法は、おそらくget<N>()
関数テンプレートを提供することです。
ただしget
、関数テンプレートは部分的に特化できないため、直接実装することはできません。SFINAE (read: boost::enable_if
) を使用するか、実際の関数をget
部分的に特殊化できる型に委譲する必要があります。
以下では後者にしました。しかし、最初にnth_type
、関数の適切な戻り値の型を返す別のヘルパー型特性が必要get
です:
template <unsigned N, typename... Args>
struct nth_type;
template <unsigned N, typename T, typename... Args>
struct nth_type<N, T, Args...> : nth_type<N - 1, Args...> { };
template <typename T, typename... Args>
struct nth_type<0, T, Args...> {
typedef T type;
};
簡単です。タイプのリストのn番目のタイプを返すだけです。
これで関数を書くことができますget
:
template <unsigned N, typename... Args>
inline typename nth_type<N, Args...>::type get(tuple<Args...>& tup) {
return get_t<N, Args...>::value(tup);
}
私が言ったように、これはタスクを委任するだけです。大したことはありません。実際には、タプルに別のオーバーロードが必要になる可能性がありconst
ます (ただし、実際には、既存のtuple
型を使用します)。
さて、殺しに続いて、軽いサラダが続きます:
template <unsigned N, typename... Args>
struct get_t;
template <unsigned N, typename T, typename... Args>
struct get_t<N, T, Args...> {
static typename nth_type<N, T, Args...>::type value(tuple<T, Args...>& tup) {
return get_t<N - 1, Args...>::value(tup.inner);
}
};
template <typename T, typename... Args>
struct get_t<0, T, Args...> {
static T value(tuple<T, Args...>& tup) {
return tup.value;
}
};
以上です。以前に定義した変数にいくつかの値を出力することで、これをテストできます。
std::cout << get<0>(n1) << std::endl; // 23
std::cout << get<0>(n2) << std::endl; // 42
std::cout << get<0>(n3) << std::endl; // hello, world
std::cout << get<1>(n2) << std::endl; // 0.5
std::cout << get<1>(n3) << std::endl; // 3.14
std::cout << get<2>(n3) << std::endl; // 97
男、可変個のテンプレートをいじるのは楽しいです。