variadic templates なクラス

std::tuple を見ながら徐々に tuple を実装して variadic templates なクラスの書き方を知ろう的な.


tuple が tuple を継承し,更にそれが tuple を継承し… というようなかんじで,それぞれが T1, T2, T3, ... な値を保持するように実装する.
はじめのいっぽ.
http://ideone.com/kKSxW


これだと不便すぎるので I 番目の要素にアクセスする方法が欲しい.
そこで各 tuple_impl に数字でタグを付けてそれで区別できるようにする.

template <int I, class ...Ts> struct tuple_impl;
template <int I> struct tuple_impl<I> {};
template <int I, class T, class ...Ts>
struct tuple_impl<I, T, Ts...> : public tuple_impl<I+1, Ts...>
{
  T value;
};

template <class ...Ts>
struct tuple : public tuple_impl<0, Ts...>
{};

するとまず tuple の I 番目の要素の型を返すメタ関数は次のように定義し,

template <int I, class ...Ts> struct tuple_element;
template <class T, class ...Ts>
struct tuple_element<0, T, Ts...> { typedef T type; };
template <int I, class T, class ...Ts>
struct tuple_element<I, T, Ts...> { typedef typename tuple_element<I-1, Ts...>::type type; };

tuple の I 番目の要素の参照を返す関数 get を次のように定義できる.

template <int I, class T, class ...Ts>
T& get_impl(tuple_impl<I, T, Ts...>& t)
{
  return t.value;
}

template <int I, class ...Ts>
typename tuple_element<I, Ts...>::type&
get(tuple<Ts...>& t)
{
  return get_impl<I>(t);
}

http://ideone.com/Pypws


適当にコンストラクタを定義し,make_tuple できるようにする.
http://ideone.com/kX2l8


boost::compressed_pair 的なこともしてみる.std::tuple もこんなかんじになっていた.
http://ideone.com/1jF0d
最初 tuple_impl_base のほうには数字のタグを持たせなくてもいいんじゃ? と思ったけど,同じ型を複数持つようなタプルの場合に base_type が曖昧になってダメなことに気付いた.