
Testing the water, see if anyone might find this useful. Any comments/suggestions are absolutely welcome and appreciated! unique_tuple<T...>, where types in <T...> may themselves be other unqiue_tupe<...>'s, contains exactly one copy of each of the "finally nested" element types in <T...>, regardless of how many times a type appears in the type parameter pack, or how deeply it is nested inside one or more unique_tuple's in <T...>. unique_tuple<T...> differs from std::tuple<T...> and boost::fusion::set<T...> etc in that nested unique_tuple's are effectively "flattened", and elements contained are unique no matter how complex the nesting gets, or how many times or how deeply nested the element type is in <T...>. unique_tuple<T...> in a way emulates virtual inheritance, but at compile time. The implementation does NOT use virtual inheritance. implementation is available at: https://www.dropbox.com/sh/f7ur7j6jetabovj/MuhhhNWU0K/unique_tuple.h and some demonstration of uses at (tested with "clang-3.5 -std=c++1y" on mac osx/macport) https://www.dropbox.com/sh/f7ur7j6jetabovj/cy_cvpPIYc/main.cpp In the following example, t1,t2,t3 all contain exactly one A, and exactly one B: struct A{}; struct B{}; unique_tuple<A,B,A,B> t1(A{},B{}); unique_tuple<A,unique_tuple<B>,unique_tuple<A,B>> t2{B{},A{}}; // order doesn't matter in constructor // B is default constructed, empty unique_tuple (possibly nested) doesn't matter unique_tuple<A,unique_tuple<unique_tuple<>>,unique_tuple<A,B,unique_tuple<A,B,unique_tuple<A,B>>>> t3{A{}}; // unique_tuple<A,B> t4(A{},B{},A{}); // doesn't compile because more than one A is supplied // unique_tuple<A,B> t5(A{},B{},1.0); // doesn't compile because double doesn't belong There are helper classes and functions, e.g.: A& a = get<A>(t0); auto x = make_unique_tuple(A{},B{},1,1.0); // unique_tuple<A,B,int,double> static_assert( is_unique_tuple<decltype(t0)>::value, "t0 is a unique_tuple type" ); static_assert( is_element_of<A,decltype(t1)>::value, "A is an element in t1" ); static_assert( is_subset_of<decltype(t1),decltype(x)>::value, "<A,B> is a subset of <A,B,int,double>" ); static_assert( unique_tuple_size<decltype(t3)>::value == 2, "there are 2 elements in t3: A and B" ); Equality comparason exists for two unique_tuple<...>s that contain the same element types, e.g., t0 == t2 && t1 != t3; Mixed operations with std::tuple are available if std::get<typename>(std::tuple<...>) exists (c++14), which effectively requires that the element types are all unique in the std::tuple<...>. synopsis: template < typename... T > struct unique_tuple { template < typename... U > explicit constexpr unique_tuple(U&&...); template < typename... U > explicit constexpr unique_tuple(const std::tuple<U...>&); template < typename... U > explicit constexpr unique_tuple(std::tuple<U...>&&); // allocator extended constructors template < typename Alloc, typename... U > unique_tuple(std::allocator_arg_t, const Alloc& a, U&&...); template < typename Alloc, typename... U > unique_tuple(std::allocator_arg_t, const Alloc& a, const unique_tuple<U...>&); template < typename Alloc, typename... U > unique_tuple(std::allocator_arg_t, const Alloc& a, unique_tuple<U...>&&); template < typename Alloc, typename... U > unique_tuple(std::allocator_arg_t, const Alloc& a, const std::tuple<U...>&); template < typename Alloc, typename... U > unique_tuple(std::allocator_arg_t, const Alloc& a, std::tuple<U...>&&); // assign template < typename... U > unique_tuple& operator=(const unique_tuple<U...>&); template < typename... U > unique_tuple& operator=(unique_tuple<U...>&&); template < typename... U > unique_tuple& operator=(const std::tuple<U...>&); template < typename... U > unique_tuple& operator=(std::tuple<U...>&&); // swap template < typename... U > void swap(unique_tuple<U...>&); template < typename... U > void swap(std::tuple<U...>&); }; // helpers template < typename... T > unique_tuple<typename std::decay<T>::type...> make_unique_tuple(T&&... t); template < typename... T > struct unique_tuple_size<unique_tuple<T...>>; // number of unique elements template < typename T > struct is_unique_tuple; template < typename T, typename... U > struct is_element_of<T,unique_tuple<U...>>; template < typename... T, typename... U > struct is_subset_of<unique_tuple<T...>,unique_tuple<U...>>; // element access template < typename T, typename... U > T& get<T>(unique_tuple<U...>&); template < typename T, typename... U > const T& get<T>(const unique_tuple<U...>&); template < typename T, typename... U > T&& get<T>(unique_tuple<U...>&&); // equality compare template < typename... T, typename... U > bool operator==(const unique_tuple<T...>&, const unique_tuple<U...>&); template < typename... T, typename... U > bool operator==(const unique_tuple<T...>&, const std::tuple<U...>&); template < typename... T, typename... U > bool operator==(const std::tuple<T...>&, const unique_tuple<U...>&); template < typename... T, typename... U > bool operator!=(const unique_tuple<T...>&, const unique_tuple<U...>&); template < typename... T, typename... U > bool operator!=(const unique_tuple<T...>&, const std::tuple<U...>&); template < typename... T, typename... U > bool operator!=(const std::tuple<T...>&, const unique_tuple<U...>&); // swap template < typename... T, typename... U > void swap(unique_tuple<T...>&, unique_tuple<U...>&); template < typename... T, typename... U > void swap(unique_tuple<T...>&, std::tuple<U...>&); template < typename... T, typename... U > void swap(std::tuple<T...>&, unique_tuple<U...>&);