#include <utility>
#include <tuple>
template <typename T>
struct unqualified { typedef typename std::remove_cv< typename std::remove_reference<T>::type>::type type; };
template <typename... T>
struct stuff{ typedef stuff type;/* contains all the types! */ };
template <std::size_t...>
struct indices_list { typedef indices_list type; };
template <std::size_t N, std::size_t... I>
struct indices : public indices<N-1, N-1, I...> { };
template <std::size_t... I>
struct indices<0, I...> : public indices_list<I...>{ };
template <typename T>
struct tuple_indices : public indices<std::tuple_size<typename unqualified<T>::type>::value> { };
template <typename TStuff>
auto awesome_tuple_dog( TStuff&& ) {
// The first man gets the oyster, the second man gets the shell
return std::tuple<>{};
}
template <typename TStuff, typename TFinalTuple>
auto awesome_tuple_dog( TStuff&&, TFinalTuple&& tuple ) {
// A greater Tuple has been born..
return std::forward<TFinalTuple>( tuple );
}
template <std::size_t ...I, std::size_t ...J, typename... Indices, typename Tuple0, typename Tuple1, typename... Tuplen>
auto awesome_tuple_dog( stuff<indices_list<I...>, indices_list<J...>, Indices...>, Tuple0&& t0, Tuple1&& t1, Tuplen&&... tn ) {
// We know for a fact that "stuff" has ever single indices list we need, but some of it is hidden
// behind variadics. We need to unpack every single last one of the indices we need and get the 'I...' we need...
return awesome_tuple_dog(
stuff<Indices...>(), // deal with the next set of indices, and use them to unite the lesser tuples!
std::make_tuple( std::get<I>( std::forward<Tuple0>( t0 ) )..., std::get<J>( std::forward<Tuple1>( t1 ) )... ),
std::forward<Tuplen>( tn )... // keep going, consume the inferior tuples!
);
}
template <typename... Tuplen>
auto awesome_tuple_cat( Tuplen&&... tn ) {
// It doens't cut it to just have tuple_indices<Tuplen>()..., because that's another variadic who's contents
// are hard to get at in another function. Need to wrap it up in a 'stuff'
//return awesome_tuple_dog( tuple_indices<Tuplen>()..., std::forward<Tuple0>( t0 ), std::forward<Tuple1>( t1 ) );
return awesome_tuple_dog( stuff<typename tuple_indices<Tuplen>::type...>(), std::forward<Tuplen>( tn )... );
}
int main () {
std::tuple<bool, char> a;
std::tuple<short, int> b;
std::tuple<long long> c;
struct {} _ = awesome_tuple_cat( );
struct {} __ = awesome_tuple_cat( a, b );
struct {} ___ = awesome_tuple_cat( a, b, c );
}
I2luY2x1ZGUgPHV0aWxpdHk+CiNpbmNsdWRlIDx0dXBsZT4KCnRlbXBsYXRlIDx0eXBlbmFtZSBUPgpzdHJ1Y3QgdW5xdWFsaWZpZWQgeyB0eXBlZGVmIHR5cGVuYW1lIHN0ZDo6cmVtb3ZlX2N2PCB0eXBlbmFtZSBzdGQ6OnJlbW92ZV9yZWZlcmVuY2U8VD46OnR5cGU+Ojp0eXBlIHR5cGU7IH07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4gVD4Kc3RydWN0IHN0dWZmeyB0eXBlZGVmIHN0dWZmIHR5cGU7LyogY29udGFpbnMgYWxsIHRoZSB0eXBlcyEgKi8gfTsKCnRlbXBsYXRlIDxzdGQ6OnNpemVfdC4uLj4gCnN0cnVjdCBpbmRpY2VzX2xpc3QgeyB0eXBlZGVmIGluZGljZXNfbGlzdCB0eXBlOyB9OwoKdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IE4sIHN0ZDo6c2l6ZV90Li4uIEk+CnN0cnVjdCBpbmRpY2VzIDogcHVibGljIGluZGljZXM8Ti0xLCBOLTEsIEkuLi4+IHsgfTsKCnRlbXBsYXRlIDxzdGQ6OnNpemVfdC4uLiBJPgpzdHJ1Y3QgaW5kaWNlczwwLCBJLi4uPiA6IHB1YmxpYyBpbmRpY2VzX2xpc3Q8SS4uLj57IH07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IHR1cGxlX2luZGljZXMgOiBwdWJsaWMgaW5kaWNlczxzdGQ6OnR1cGxlX3NpemU8dHlwZW5hbWUgdW5xdWFsaWZpZWQ8VD46OnR5cGU+Ojp2YWx1ZT4geyB9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFRTdHVmZj4KYXV0byBhd2Vzb21lX3R1cGxlX2RvZyggVFN0dWZmJiYgKSB7CgkvLyBUaGUgZmlyc3QgbWFuIGdldHMgdGhlIG95c3RlciwgdGhlIHNlY29uZCBtYW4gZ2V0cyB0aGUgc2hlbGwKCXJldHVybiBzdGQ6OnR1cGxlPD57fTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIFRTdHVmZiwgdHlwZW5hbWUgVEZpbmFsVHVwbGU+CmF1dG8gYXdlc29tZV90dXBsZV9kb2coIFRTdHVmZiYmLCBURmluYWxUdXBsZSYmIHR1cGxlICkgewoJLy8gQSBncmVhdGVyIFR1cGxlIGhhcyBiZWVuIGJvcm4uLgoJcmV0dXJuIHN0ZDo6Zm9yd2FyZDxURmluYWxUdXBsZT4oIHR1cGxlICk7Cn0KCnRlbXBsYXRlIDxzdGQ6OnNpemVfdCAuLi5JLCBzdGQ6OnNpemVfdCAuLi5KLCB0eXBlbmFtZS4uLiBJbmRpY2VzLCB0eXBlbmFtZSBUdXBsZTAsIHR5cGVuYW1lIFR1cGxlMSwgdHlwZW5hbWUuLi4gVHVwbGVuPgphdXRvIGF3ZXNvbWVfdHVwbGVfZG9nKCBzdHVmZjxpbmRpY2VzX2xpc3Q8SS4uLj4sIGluZGljZXNfbGlzdDxKLi4uPiwgSW5kaWNlcy4uLj4sIFR1cGxlMCYmIHQwLCBUdXBsZTEmJiB0MSwgVHVwbGVuJiYuLi4gdG4gKSB7CiAgICAvLyBXZSBrbm93IGZvciBhIGZhY3QgdGhhdCAic3R1ZmYiIGhhcyBldmVyIHNpbmdsZSBpbmRpY2VzIGxpc3Qgd2UgbmVlZCwgYnV0IHNvbWUgb2YgaXQgaXMgaGlkZGVuCiAgICAvLyBiZWhpbmQgdmFyaWFkaWNzLiBXZSBuZWVkIHRvIHVucGFjayBldmVyeSBzaW5nbGUgbGFzdCBvbmUgb2YgdGhlIGluZGljZXMgd2UgbmVlZCBhbmQgZ2V0IHRoZSAnSS4uLicgd2UgbmVlZC4uLgogICAgcmV0dXJuIGF3ZXNvbWVfdHVwbGVfZG9nKCAKICAgICAgICBzdHVmZjxJbmRpY2VzLi4uPigpLCAvLyBkZWFsIHdpdGggdGhlIG5leHQgc2V0IG9mIGluZGljZXMsIGFuZCB1c2UgdGhlbSB0byB1bml0ZSB0aGUgbGVzc2VyIHR1cGxlcyEKICAgICAgICBzdGQ6Om1ha2VfdHVwbGUoIHN0ZDo6Z2V0PEk+KCBzdGQ6OmZvcndhcmQ8VHVwbGUwPiggdDAgKSApLi4uLCBzdGQ6OmdldDxKPiggc3RkOjpmb3J3YXJkPFR1cGxlMT4oIHQxICkgKS4uLiApLAogICAgICAgIHN0ZDo6Zm9yd2FyZDxUdXBsZW4+KCB0biApLi4uIC8vIGtlZXAgZ29pbmcsIGNvbnN1bWUgdGhlIGluZmVyaW9yIHR1cGxlcyEKICAgICAgICApOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4gVHVwbGVuPgphdXRvIGF3ZXNvbWVfdHVwbGVfY2F0KCBUdXBsZW4mJi4uLiB0biApIHsKICAgIC8vIEl0IGRvZW5zJ3QgY3V0IGl0IHRvIGp1c3QgaGF2ZSB0dXBsZV9pbmRpY2VzPFR1cGxlbj4oKS4uLiwgYmVjYXVzZSB0aGF0J3MgYW5vdGhlciB2YXJpYWRpYyB3aG8ncyBjb250ZW50cwogICAgLy8gYXJlIGhhcmQgdG8gZ2V0IGF0IGluIGFub3RoZXIgZnVuY3Rpb24uIE5lZWQgdG8gd3JhcCBpdCB1cCBpbiBhICdzdHVmZicKICAgIC8vcmV0dXJuIGF3ZXNvbWVfdHVwbGVfZG9nKCB0dXBsZV9pbmRpY2VzPFR1cGxlbj4oKS4uLiwgc3RkOjpmb3J3YXJkPFR1cGxlMD4oIHQwICksIHN0ZDo6Zm9yd2FyZDxUdXBsZTE+KCB0MSApICk7CiAgICByZXR1cm4gYXdlc29tZV90dXBsZV9kb2coIHN0dWZmPHR5cGVuYW1lIHR1cGxlX2luZGljZXM8VHVwbGVuPjo6dHlwZS4uLj4oKSwgc3RkOjpmb3J3YXJkPFR1cGxlbj4oIHRuICkuLi4gKTsKfQoKaW50IG1haW4gKCkgewogICAgc3RkOjp0dXBsZTxib29sLCBjaGFyPiBhOwogICAgc3RkOjp0dXBsZTxzaG9ydCwgaW50PiBiOwogICAgc3RkOjp0dXBsZTxsb25nIGxvbmc+IGM7CiAgICBzdHJ1Y3Qge30gXyA9IGF3ZXNvbWVfdHVwbGVfY2F0KCApOwogICAgc3RydWN0IHt9IF9fID0gYXdlc29tZV90dXBsZV9jYXQoIGEsIGIgKTsKICAgIHN0cnVjdCB7fSBfX18gPSBhd2Vzb21lX3R1cGxlX2NhdCggYSwgYiwgYyApOwogICAgCn0=
prog.cpp:23:34: warning: ‘awesome_tuple_dog’ function uses ‘auto’ type specifier without trailing return type [enabled by default]
auto awesome_tuple_dog( TStuff&& ) {
^
prog.cpp:29:55: warning: ‘awesome_tuple_dog’ function uses ‘auto’ type specifier without trailing return type [enabled by default]
auto awesome_tuple_dog( TStuff&&, TFinalTuple&& tuple ) {
^
prog.cpp:35:125: warning: ‘awesome_tuple_dog’ function uses ‘auto’ type specifier without trailing return type [enabled by default]
auto awesome_tuple_dog( stuff<indices_list<I...>, indices_list<J...>, Indices...>, Tuple0&& t0, Tuple1&& t1, Tuplen&&... tn ) {
^
prog.cpp:46:40: warning: ‘awesome_tuple_cat’ function uses ‘auto’ type specifier without trailing return type [enabled by default]
auto awesome_tuple_cat( Tuplen&&... tn ) {
^
prog.cpp: In function ‘int main()’:
prog.cpp:57:38: error: conversion from ‘std::tuple<>’ to non-scalar type ‘main()::<anonymous struct>’ requested
struct {} _ = awesome_tuple_cat( );
^
prog.cpp:58:44: error: conversion from ‘std::tuple<bool, char, short int, int>’ to non-scalar type ‘main()::<anonymous struct>’ requested
struct {} __ = awesome_tuple_cat( a, b );
^
prog.cpp: In instantiation of ‘auto awesome_tuple_dog(stuff<indices_list<I ...>, indices_list<J ...>, Indices ...>, Tuple0&&, Tuple1&&, Tuplen&& ...) [with unsigned int ...I = {0u, 1u}; unsigned int ...J = {0u, 1u}; Indices = {indices_list<0u>}; Tuple0 = std::tuple<bool, char>&; Tuple1 = std::tuple<short int, int>&; Tuplen = {std::tuple<long long int>&}]’:
prog.cpp:50:111: required from ‘auto awesome_tuple_cat(Tuplen&& ...) [with Tuplen = {std::tuple<bool, char>&, std::tuple<short int, int>&, std::tuple<long long int>&}]’
prog.cpp:59:48: required from here
prog.cpp:42:9: error: no matching function for call to ‘awesome_tuple_dog(stuff<indices_list<0u> >, std::tuple<bool, char, short int, int>, std::tuple<long long int>&)’
);
^
prog.cpp:42:9: note: candidates are:
prog.cpp:23:6: note: template<class TStuff> auto awesome_tuple_dog(TStuff&&)
auto awesome_tuple_dog( TStuff&& ) {
^
prog.cpp:23:6: note: template argument deduction/substitution failed:
prog.cpp:42:9: note: candidate expects 1 argument, 3 provided
);
^
prog.cpp:29:6: note: template<class TStuff, class TFinalTuple> auto awesome_tuple_dog(TStuff&&, TFinalTuple&&)
auto awesome_tuple_dog( TStuff&&, TFinalTuple&& tuple ) {
^
prog.cpp:29:6: note: template argument deduction/substitution failed:
prog.cpp:42:9: note: candidate expects 2 arguments, 3 provided
);
^
prog.cpp:35:6: note: template<unsigned int ...I, unsigned int ...J, class ... Indices, class Tuple0, class Tuple1, class ... Tuplen> auto awesome_tuple_dog(stuff<indices_list<I ...>, indices_list<J ...>, Indices ...>, Tuple0&&, Tuple1&&, Tuplen&& ...)
auto awesome_tuple_dog( stuff<indices_list<I...>, indices_list<J...>, Indices...>, Tuple0&& t0, Tuple1&& t1, Tuplen&&... tn ) {
^
prog.cpp:35:6: note: template argument deduction/substitution failed:
prog.cpp:42:9: note: candidate expects 3 arguments, 1 provided
);
^
prog.cpp:42:9: note: ‘stuff<indices_list<0u> >’ is not derived from ‘stuff<indices_list<I ...>, indices_list<J ...>, Indices ...>’
prog.cpp:59:48: error: conversion from ‘void’ to non-scalar type ‘main()::<anonymous struct>’ requested
struct {} ___ = awesome_tuple_cat( a, b, c );
^