// http://w...content-available-to-author-only...t.org/doc/libs/1_66_0_beta1/libs/mp11/doc/html/simple_cxx11_metaprogramming.html
#include <tuple>
#include <type_traits>
// Tuple concatenation:
// tuple<a...>, tuple<b...>, ... -> tuple<a..., b..., ...>
template <class A, class B>
struct Tcat;
template <class... T, class... S>
struct Tcat<std::tuple<T...>, std::tuple<S...>>
{
using type = std::tuple<T..., S...>;
};
template <class A, class B>
using tcat = typename Tcat<A, B>::type;
template <class... A> struct Tcats;
template <class... T>
struct Tcats<std::tuple<T...>>
{
using type = std::tuple<T...>;
};
template <class A, class B, class... Other>
struct Tcats<A, B, Other...>
{
using type = typename Tcats<tcat<A, B>, Other...>::type;
};
template <class... T>
using tcats = typename Tcats<T...>::type;
// Transpose (generic "zip"):
// F, tuple<tuple<a,b,c>, tuple<d,e,f>> ->
// tuple<F<a,d>, F<b,e>, F<c,f>>
// -- any number of tuples -- arguments of F.
// where F is any template<class...> class.
// Select the column I from the T... matrix.
template <class I,
template <class...> class F, class... T>
struct Tcol
{
using type = F<std::tuple_element_t<I::value, T>...>;
};
template <class I,
template <class...> class F, class... T>
using tcol = typename Tcol<I, F, T...>::type;
// Make range S, S+1, S+2, ..., T-1
// as a tuple of integer_constant.
template <class S, class T,
template <class...> class F, class... Other>
struct Tfor;
template <class Int, Int s,
template <class...> class F, class... Other>
struct Tfor<
std::integral_constant<Int, s>,
std::integral_constant<Int, s>,
F, Other...>
{
using type = std::tuple<>;
};
template <class Int, Int s, Int t,
template <class...> class F, class... Other>
struct Tfor<
std::integral_constant<Int, s>,
std::integral_constant<Int, t>,
F, Other...>
{
static_assert(s < t, "");
using S = std::integral_constant<Int, s>;
using S1 = std::integral_constant<Int, s+1>;
using T = std::integral_constant<Int, t>;
using type = tcat<std::tuple<F<S, Other...>>,
typename Tfor<S1, T, F, Other...>::type>;
};
template <class S, class T,
template <class...> class F, class... Other>
using tfor = typename Tfor<S, T, F, Other...>::type;
template <
template <class...> class F,
class... T>
struct Tzip;
template <
template <class...> class F>
struct Tzip<F> { using type = std::tuple<>; };
template <
template <class...> class F,
class T0, class... T>
struct Tzip<F, T0, T...>
{
template <class I, class... Y>
using tcolF = tcol<I, F, Y...>;
using type = tfor<
std::integral_constant<std::size_t, 0>,
std::integral_constant<std::size_t, std::tuple_size<T0>::value>,
tcolF, T0, T...>;
};
template <
template <class...> class F,
class... T>
using tzip = typename Tzip<F, T...>::type;
//////////////////////////////////////////////////
// Testing
template <class... T>
struct Tmax;
template <class T>
struct Tmax<T> { using type = T; };
template <class T0, class... T>
struct Tmax<T0, T...>
{
using tail_max = typename Tmax<T...>::type;
using type = std::conditional_t<
(T0::value < tail_max::value), tail_max, T0>;
};
template <class... T>
using tmax = typename Tmax<T...>::type;
template <class T>
using Sizeof = std::integral_constant<std::size_t, sizeof(T)>;
template <class... T>
using tmax_sizeof = tmax<Sizeof<T>...>;
int main()
{
using namespace std;
// Concat.
{
using t0 = tuple<int, int*>;
using t1 = tuple<float>;
using t2 = tuple<char*, char**, void*, void**>;
using t3 = tuple<>;
using ex = tuple<int, int*, float, char*, char**, void*, void**>;
static_assert(is_same<tcats<t0, t1, t2, t3>, ex>::value, "");
}
// Generic zip.
{
using r0 = tuple<char, short, int, long>;
using r1 = tuple<unsigned, void*, void**, void***>;
using exr = tuple<
tuple<char, unsigned>,
tuple<short, void*>,
tuple<int, void**>,
tuple<long, void***>>;
//print_t(tzip<tuple, r0, r1>{});
static_assert(is_same<exr, tzip<tuple, r0, r1>>::value, "");
using t0 = tuple<int[11], int[12], int[13]>;
using t1 = tuple<int[21], int[22], int[23]>;
using t2 = tuple<int[31], int[32], int[33]>;
using t3 = tuple<int[41], int[42], int[43]>;
using ext = tuple<
tuple<int[11], int[21], int[31], int[41]>,
tuple<int[12], int[22], int[32], int[42]>,
tuple<int[13], int[23], int[33], int[43]>>;
static_assert(is_same<ext, tzip<tuple, t0, t1, t2, t3>>::value, "");
using exsz = tuple<
Sizeof<int[41]>, Sizeof<int[42]>, Sizeof<int[43]>>;
static_assert(is_same<exsz, tzip<tmax_sizeof, t0, t1, t2, t3>>::value, "");
}
return 0;
}
Ly8gaHR0cDovL3cuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLnQub3JnL2RvYy9saWJzLzFfNjZfMF9iZXRhMS9saWJzL21wMTEvZG9jL2h0bWwvc2ltcGxlX2N4eDExX21ldGFwcm9ncmFtbWluZy5odG1sCiNpbmNsdWRlIDx0dXBsZT4KI2luY2x1ZGUgPHR5cGVfdHJhaXRzPgoKLy8gVHVwbGUgY29uY2F0ZW5hdGlvbjoKLy8gdHVwbGU8YS4uLj4sIHR1cGxlPGIuLi4+LCAuLi4gLT4gdHVwbGU8YS4uLiwgYi4uLiwgLi4uPgoKdGVtcGxhdGUgPGNsYXNzIEEsIGNsYXNzIEI+CnN0cnVjdCBUY2F0OwoKdGVtcGxhdGUgPGNsYXNzLi4uIFQsIGNsYXNzLi4uIFM+CnN0cnVjdCBUY2F0PHN0ZDo6dHVwbGU8VC4uLj4sIHN0ZDo6dHVwbGU8Uy4uLj4+CnsKICB1c2luZyB0eXBlID0gc3RkOjp0dXBsZTxULi4uLCBTLi4uPjsKfTsKCnRlbXBsYXRlIDxjbGFzcyBBLCBjbGFzcyBCPgp1c2luZyB0Y2F0ID0gdHlwZW5hbWUgVGNhdDxBLCBCPjo6dHlwZTsKCgp0ZW1wbGF0ZSA8Y2xhc3MuLi4gQT4gc3RydWN0IFRjYXRzOwoKdGVtcGxhdGUgPGNsYXNzLi4uIFQ+CnN0cnVjdCBUY2F0czxzdGQ6OnR1cGxlPFQuLi4+Pgp7CiAgdXNpbmcgdHlwZSA9IHN0ZDo6dHVwbGU8VC4uLj47Cn07Cgp0ZW1wbGF0ZSA8Y2xhc3MgQSwgY2xhc3MgQiwgY2xhc3MuLi4gT3RoZXI+CnN0cnVjdCBUY2F0czxBLCBCLCBPdGhlci4uLj4KewogIHVzaW5nIHR5cGUgPSB0eXBlbmFtZSBUY2F0czx0Y2F0PEEsIEI+LCBPdGhlci4uLj46OnR5cGU7Cn07Cgp0ZW1wbGF0ZSA8Y2xhc3MuLi4gVD4KdXNpbmcgdGNhdHMgPSB0eXBlbmFtZSBUY2F0czxULi4uPjo6dHlwZTsKCgovLyBUcmFuc3Bvc2UgKGdlbmVyaWMgInppcCIpOgovLyBGLCB0dXBsZTx0dXBsZTxhLGIsYz4sIHR1cGxlPGQsZSxmPj4gLT4KLy8gdHVwbGU8RjxhLGQ+LCBGPGIsZT4sIEY8YyxmPj4KLy8gLS0gYW55IG51bWJlciBvZiB0dXBsZXMgLS0gYXJndW1lbnRzIG9mIEYuCi8vIHdoZXJlIEYgaXMgYW55IHRlbXBsYXRlPGNsYXNzLi4uPiBjbGFzcy4KCi8vIFNlbGVjdCB0aGUgY29sdW1uIEkgZnJvbSB0aGUgVC4uLiBtYXRyaXguCnRlbXBsYXRlIDxjbGFzcyBJLAogIHRlbXBsYXRlIDxjbGFzcy4uLj4gY2xhc3MgRiwgY2xhc3MuLi4gVD4Kc3RydWN0IFRjb2wKewogIHVzaW5nIHR5cGUgPSBGPHN0ZDo6dHVwbGVfZWxlbWVudF90PEk6OnZhbHVlLCBUPi4uLj47Cn07Cgp0ZW1wbGF0ZSA8Y2xhc3MgSSwKICB0ZW1wbGF0ZSA8Y2xhc3MuLi4+IGNsYXNzIEYsIGNsYXNzLi4uIFQ+CnVzaW5nIHRjb2wgPSB0eXBlbmFtZSBUY29sPEksIEYsIFQuLi4+Ojp0eXBlOwoKLy8gTWFrZSByYW5nZSBTLCBTKzEsIFMrMiwgLi4uLCBULTEKLy8gYXMgYSB0dXBsZSBvZiBpbnRlZ2VyX2NvbnN0YW50Lgp0ZW1wbGF0ZSA8Y2xhc3MgUywgY2xhc3MgVCwKICB0ZW1wbGF0ZSA8Y2xhc3MuLi4+IGNsYXNzIEYsIGNsYXNzLi4uIE90aGVyPgpzdHJ1Y3QgVGZvcjsKCnRlbXBsYXRlIDxjbGFzcyBJbnQsIEludCBzLAogIHRlbXBsYXRlIDxjbGFzcy4uLj4gY2xhc3MgRiwgY2xhc3MuLi4gT3RoZXI+CnN0cnVjdCBUZm9yPAogIHN0ZDo6aW50ZWdyYWxfY29uc3RhbnQ8SW50LCBzPiwKICBzdGQ6OmludGVncmFsX2NvbnN0YW50PEludCwgcz4sCiAgRiwgT3RoZXIuLi4+CnsKICB1c2luZyB0eXBlID0gc3RkOjp0dXBsZTw+Owp9OwoKdGVtcGxhdGUgPGNsYXNzIEludCwgSW50IHMsIEludCB0LAogIHRlbXBsYXRlIDxjbGFzcy4uLj4gY2xhc3MgRiwgY2xhc3MuLi4gT3RoZXI+CnN0cnVjdCBUZm9yPAogIHN0ZDo6aW50ZWdyYWxfY29uc3RhbnQ8SW50LCBzPiwKICBzdGQ6OmludGVncmFsX2NvbnN0YW50PEludCwgdD4sCiAgRiwgT3RoZXIuLi4+CnsKICBzdGF0aWNfYXNzZXJ0KHMgPCB0LCAiIik7CiAgdXNpbmcgUyAgPSBzdGQ6OmludGVncmFsX2NvbnN0YW50PEludCwgcz47CiAgdXNpbmcgUzEgPSBzdGQ6OmludGVncmFsX2NvbnN0YW50PEludCwgcysxPjsKICB1c2luZyBUICA9IHN0ZDo6aW50ZWdyYWxfY29uc3RhbnQ8SW50LCB0PjsKICAKICB1c2luZyB0eXBlID0gdGNhdDxzdGQ6OnR1cGxlPEY8UywgT3RoZXIuLi4+PiwKICAgIHR5cGVuYW1lIFRmb3I8UzEsIFQsIEYsIE90aGVyLi4uPjo6dHlwZT47Cn07Cgp0ZW1wbGF0ZSA8Y2xhc3MgUywgY2xhc3MgVCwKICB0ZW1wbGF0ZSA8Y2xhc3MuLi4+IGNsYXNzIEYsIGNsYXNzLi4uIE90aGVyPgp1c2luZyB0Zm9yID0gdHlwZW5hbWUgVGZvcjxTLCBULCBGLCBPdGhlci4uLj46OnR5cGU7Cgp0ZW1wbGF0ZSA8CiAgdGVtcGxhdGUgPGNsYXNzLi4uPiBjbGFzcyBGLAogIGNsYXNzLi4uIFQ+CnN0cnVjdCBUemlwOwoKdGVtcGxhdGUgPAogIHRlbXBsYXRlIDxjbGFzcy4uLj4gY2xhc3MgRj4Kc3RydWN0IFR6aXA8Rj4geyB1c2luZyB0eXBlID0gc3RkOjp0dXBsZTw+OyB9OwoKdGVtcGxhdGUgPAogIHRlbXBsYXRlIDxjbGFzcy4uLj4gY2xhc3MgRiwKICBjbGFzcyBUMCwgY2xhc3MuLi4gVD4Kc3RydWN0IFR6aXA8RiwgVDAsIFQuLi4+CnsKICB0ZW1wbGF0ZSA8Y2xhc3MgSSwgY2xhc3MuLi4gWT4KICB1c2luZyB0Y29sRiA9IHRjb2w8SSwgRiwgWS4uLj47CiAgdXNpbmcgdHlwZSA9IHRmb3I8CiAgICBzdGQ6OmludGVncmFsX2NvbnN0YW50PHN0ZDo6c2l6ZV90LCAwPiwKICAgIHN0ZDo6aW50ZWdyYWxfY29uc3RhbnQ8c3RkOjpzaXplX3QsIHN0ZDo6dHVwbGVfc2l6ZTxUMD46OnZhbHVlPiwKICAgIHRjb2xGLCBUMCwgVC4uLj47Cn07Cgp0ZW1wbGF0ZSA8CiAgdGVtcGxhdGUgPGNsYXNzLi4uPiBjbGFzcyBGLAogIGNsYXNzLi4uIFQ+CnVzaW5nIHR6aXAgPSB0eXBlbmFtZSBUemlwPEYsIFQuLi4+Ojp0eXBlOwoKCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCi8vIFRlc3RpbmcKCnRlbXBsYXRlIDxjbGFzcy4uLiBUPgpzdHJ1Y3QgVG1heDsKCnRlbXBsYXRlIDxjbGFzcyBUPgpzdHJ1Y3QgVG1heDxUPiB7IHVzaW5nIHR5cGUgPSBUOyB9OwoKdGVtcGxhdGUgPGNsYXNzIFQwLCBjbGFzcy4uLiBUPgpzdHJ1Y3QgVG1heDxUMCwgVC4uLj4KewogIHVzaW5nIHRhaWxfbWF4ID0gdHlwZW5hbWUgVG1heDxULi4uPjo6dHlwZTsKICB1c2luZyB0eXBlID0gc3RkOjpjb25kaXRpb25hbF90PAogICAgKFQwOjp2YWx1ZSA8IHRhaWxfbWF4Ojp2YWx1ZSksIHRhaWxfbWF4LCBUMD47Cn07Cgp0ZW1wbGF0ZSA8Y2xhc3MuLi4gVD4KdXNpbmcgdG1heCA9IHR5cGVuYW1lIFRtYXg8VC4uLj46OnR5cGU7Cgp0ZW1wbGF0ZSA8Y2xhc3MgVD4KdXNpbmcgU2l6ZW9mID0gc3RkOjppbnRlZ3JhbF9jb25zdGFudDxzdGQ6OnNpemVfdCwgc2l6ZW9mKFQpPjsKCnRlbXBsYXRlIDxjbGFzcy4uLiBUPgp1c2luZyB0bWF4X3NpemVvZiA9IHRtYXg8U2l6ZW9mPFQ+Li4uPjsKCmludCBtYWluKCkKewogIHVzaW5nIG5hbWVzcGFjZSBzdGQ7CiAgLy8gQ29uY2F0LgogIHsKICAgIHVzaW5nIHQwID0gdHVwbGU8aW50LCBpbnQqPjsKICAgIHVzaW5nIHQxID0gdHVwbGU8ZmxvYXQ+OwogICAgdXNpbmcgdDIgPSB0dXBsZTxjaGFyKiwgY2hhcioqLCB2b2lkKiwgdm9pZCoqPjsKICAgIHVzaW5nIHQzID0gdHVwbGU8PjsKICAgIHVzaW5nIGV4ID0gdHVwbGU8aW50LCBpbnQqLCBmbG9hdCwgY2hhciosIGNoYXIqKiwgdm9pZCosIHZvaWQqKj47CiAgICBzdGF0aWNfYXNzZXJ0KGlzX3NhbWU8dGNhdHM8dDAsIHQxLCB0MiwgdDM+LCBleD46OnZhbHVlLCAiIik7CiAgfQogIAogIC8vIEdlbmVyaWMgemlwLgogIHsKICAgIHVzaW5nIHIwID0gdHVwbGU8Y2hhciwgc2hvcnQsIGludCwgbG9uZz47CiAgICB1c2luZyByMSA9IHR1cGxlPHVuc2lnbmVkLCB2b2lkKiwgdm9pZCoqLCB2b2lkKioqPjsKICAgIHVzaW5nIGV4ciA9IHR1cGxlPAogICAgICB0dXBsZTxjaGFyLCB1bnNpZ25lZD4sCiAgICAgIHR1cGxlPHNob3J0LCB2b2lkKj4sCiAgICAgIHR1cGxlPGludCwgdm9pZCoqPiwKICAgICAgdHVwbGU8bG9uZywgdm9pZCoqKj4+OwogICAgLy9wcmludF90KHR6aXA8dHVwbGUsIHIwLCByMT57fSk7CiAgICBzdGF0aWNfYXNzZXJ0KGlzX3NhbWU8ZXhyLCB0emlwPHR1cGxlLCByMCwgcjE+Pjo6dmFsdWUsICIiKTsKICAgIAogICAgdXNpbmcgdDAgPSB0dXBsZTxpbnRbMTFdLCBpbnRbMTJdLCBpbnRbMTNdPjsKICAgIHVzaW5nIHQxID0gdHVwbGU8aW50WzIxXSwgaW50WzIyXSwgaW50WzIzXT47CiAgICB1c2luZyB0MiA9IHR1cGxlPGludFszMV0sIGludFszMl0sIGludFszM10+OwogICAgdXNpbmcgdDMgPSB0dXBsZTxpbnRbNDFdLCBpbnRbNDJdLCBpbnRbNDNdPjsKICAgIHVzaW5nIGV4dCA9IHR1cGxlPAogICAgICB0dXBsZTxpbnRbMTFdLCBpbnRbMjFdLCBpbnRbMzFdLCBpbnRbNDFdPiwKICAgICAgdHVwbGU8aW50WzEyXSwgaW50WzIyXSwgaW50WzMyXSwgaW50WzQyXT4sCiAgICAgIHR1cGxlPGludFsxM10sIGludFsyM10sIGludFszM10sIGludFs0M10+PjsKICAgIHN0YXRpY19hc3NlcnQoaXNfc2FtZTxleHQsIHR6aXA8dHVwbGUsIHQwLCB0MSwgdDIsIHQzPj46OnZhbHVlLCAiIik7CiAgICAKICAgIHVzaW5nIGV4c3ogPSB0dXBsZTwKICAgICAgU2l6ZW9mPGludFs0MV0+LCBTaXplb2Y8aW50WzQyXT4sIFNpemVvZjxpbnRbNDNdPj47CiAgICBzdGF0aWNfYXNzZXJ0KGlzX3NhbWU8ZXhzeiwgdHppcDx0bWF4X3NpemVvZiwgdDAsIHQxLCB0MiwgdDM+Pjo6dmFsdWUsICIiKTsKICB9CiAgCiAgcmV0dXJuIDA7Cn0K