Skip to content

Instantly share code, notes, and snippets.

@jaredhoberock
Created February 28, 2015 02:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jaredhoberock/f42026101412578172cc to your computer and use it in GitHub Desktop.
Save jaredhoberock/f42026101412578172cc to your computer and use it in GitHub Desktop.
Empty tuples
#include <type_traits>
#include <cassert>
template<int i, class Whence, class T, bool = std::is_empty<T>::value>
struct tuple_leaf
{
tuple_leaf(T x) : val(x) {}
T& get() { return val; }
T val;
};
template<int i, class Whence, class T>
struct tuple_leaf<i,Whence,T,true> : private T
{
tuple_leaf(T x) : T(x) {}
T& get() { return *this; }
};
template<int i, class T1, class T2>
struct type_at
{
using type = T1;
};
template<class T1, class T2>
struct type_at<1,T1,T2>
{
using type = T2;
};
template<class T1, class T2>
struct tuple_base : tuple_leaf<0,tuple_base<T1,T2>,T1>, tuple_leaf<1,tuple_base<T1,T2>,T2>
{
tuple_base(T1 a, T2 b) : tuple_leaf<0,tuple_base<T1,T2>,T1>(a), tuple_leaf<1,tuple_base<T1,T2>,T2>(b) {}
template<int i>
tuple_leaf<i,tuple_base,typename type_at<i,T1,T2>::type> get_leaf()
{
// XXX how to disambiguate this conversion?
return *this;
}
};
// XXX deriving from tuple_base rather than creating
// making tuple_base a member is the root of the issue
template<class T1, class T2>
struct my_tuple : tuple_base<T1,T2>
{
my_tuple(T1 a, T2 b) : tuple_base<T1,T2>(a, b) {}
};
template<int i, class T1, class T2>
typename type_at<i,T1,T2>::type& get(my_tuple<T1,T2>& t)
{
return (t.template get_leaf<i>()).get();
}
template<class T1,class T2>
my_tuple<T1,T2> make_tuple(T1 a, T2 b)
{
return my_tuple<T1,T2>(a,b);
}
struct empty {};
int main()
{
auto tuple = make_tuple(empty(), make_tuple(empty(),empty()));
assert(std::is_empty<decltype(tuple)>::value == true);
get<0>(tuple);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment