lnicola
6/20/2014 - 4:06 PM

std::tuple-like class

std::tuple-like class

#include <cstdio>
#include <utility>

template<typename...>
class tuple { };

template<typename T, typename... U>
class tuple<T, U...> : tuple<U...>
{
public:
   T value;

   tuple(T&& value, U&&... values)
      : tuple<U...>(std::forward<U>(values)...), value(std::forward<T>(value)) { }
};

template<typename... T>
tuple<T...> make_tuple(T&& ... values)
{
   return tuple<T...>(std::forward<T>(values)...);
}

template<size_t, typename...>
struct tuple_info;

template<size_t pos, typename T, typename... U>
struct tuple_info<pos, T, U...>
{
   typedef typename tuple_info<pos - 1, U...>::tuple_type tuple_type;
   typedef typename tuple_info<pos - 1, U...>::element_type element_type;
};

template<typename T, typename... U>
struct tuple_info<0, T, U...>
{
   typedef tuple<T, U...> tuple_type;
   typedef T element_type;
};

template<size_t pos, typename... T>
const typename tuple_info<pos, T...>::element_type & get(const tuple<T...> &t)
{
   return reinterpret_cast<const typename tuple_info<pos, T...>::tuple_type &>(t).value;
}

template<size_t pos, typename... T>
typename tuple_info<pos, T...>::element_type & get(tuple<T...> &t)
{
   return reinterpret_cast<typename tuple_info<pos, T...>::tuple_type &>(t).value;
}

template<size_t pos, typename... T>
typename tuple_info<pos, T...>::element_type & get(tuple<T...> &&t)
{
   return reinterpret_cast<typename tuple_info<pos, T...>::tuple_type &>(t).value;
}

int main()
{
   make_tuple();

   auto foo = make_tuple(1, 2, 3);
   std::printf("%d %d %d", get<0>(foo), get<1>(foo), get<2>(foo));
   get<2>(foo) = 4;
   std::printf(" %d\n", get<2>(foo));

   get<2>(make_tuple(1, 2, 3)) = 4;

   const auto bar = make_tuple(1, 2, 3);
   std::printf("%d %d %d\n", get<0>(bar), get<1>(bar), get<2>(bar));
}