#include <iostream>
#include <type_traits>
template <int I> using int_ = std::integral_constant<int, I>;
template<typename T> using eval = typename T::type;
template<typename... List>
struct seq
{
using type = seq;
};
template<typename> struct car;
template<typename Car, typename... Cdr>
struct car< seq<Car, Cdr...>>
{
typedef Car type;
};
template<typename> struct cdr;
template<typename Car, typename... Cdr>
struct cdr< seq<Car, Cdr...>>
{
typedef seq<Cdr...> type;
};
template <typename, typename> struct cons;
template <typename T, typename... L>
struct cons<T, seq<L...>>
{
typedef seq<T, L...> type;
};
//template <typename T>
//struct cons<T, seq<>>
//{
// typedef seq<T> type;
//};
template<typename, typename> struct concat;
template <typename... As, typename... Bs>
struct concat<seq<As...>, seq<Bs...>>
{
typedef seq<As..., Bs...> type;
};
template<typename> struct length;
template<typename... As>
struct length<seq<As...>>
{
typedef std::integral_constant<unsigned, sizeof...(As)> type;
};
template<typename>
struct is_empty
{
typedef std::integral_constant<bool, false> type;
};
template<>
struct is_empty<seq<>>
{
typedef std::integral_constant<bool, true> type;
};
template<template<typename... Args> class Fun, typename... Args>
struct apply
{
typedef eval<Fun<Args...>> type;
};
template<typename B, typename C, typename A> struct cond;
template<typename C, typename A>
struct cond<std::true_type, C, A>
{
typedef C type;
};
template<typename C, typename A>
struct cond<std::false_type, C, A>
{
typedef A type;
};
//template<typename, typename> struct map;
//template<typename A, typename... As, template<typename A> class F>
//struct map<seq<A, As...>, F>
//{
// //typedef seq<eval<F<A>>...> type;
// typedef cons < eval < F < A > >
// , map < seq < As... > , F >
// > type;
//};
template <typename S, template<typename B> class F> struct map_t;
//template <template <typename B> class F, typename... Es>
template <typename... Es, template <typename B> class F>
struct map_t <seq<Es...>, F >
{
typedef typename car<seq<Es...>>::type Car;
typedef typename cdr<seq<Es...>>::type Cdr;
typedef eval< cons < eval < F < Car > >
, eval< map_t < Cdr, F > >
> > type;
};
template <template <typename B> class F>
struct map_t <seq<>, F >
{
typedef seq<> type;
};
template <typename S, template<typename B> class F> struct filter_t;
//template <template <typename B> class F, typename... Es>
template <typename... Es, template <typename B> class F>
struct filter_t <seq<Es...>, F >
{
typedef typename car<seq<Es...>>::type Car;
typedef typename cdr<seq<Es...>>::type Cdr;
typedef eval< cond < eval < F < Car > >
, eval < cons < Car, eval< filter_t < Cdr, F > > > >
, eval < filter_t < Cdr, F > >
> > type;
};
template <template <typename B> class F>
struct filter_t <seq<>, F >
{
typedef seq<> type;
};
template<typename A> struct even;
template<int I>
struct even<std::integral_constant<int, I> >
{
typedef std::integral_constant<bool, I % 2 == 0> type;
};
//template<typename> struct constant;
//template<typename T>
//struct constant<T>
//{
// typedef std::integral_constant<bool, false> type;
//};
typedef seq<int_<1>, int_<2>, int_<3> > s1;
typedef seq<int_<7>, int_<5>, int_<9> > s2;
typedef seq<int_<1>, s2, int_<17>, s1 > s3;
typedef seq<> empty;
typedef seq<int_<1>> s0;
template<typename Seq> using concat_fix = apply<concat, s2, Seq>;
int main()
{
std::cerr << eval < length < eval < apply < concat, s1, s3 >> >> ::value << '\n';
std::cerr << eval < length < eval < concat_fix < s3 >> >> ::value << '\n';
std::cerr << eval < apply < length, empty> >::value << '\n';
std::cerr << eval < length < eval < concat < s1, s3 >> >> ::value << '\n';
std::cerr << "even(2): " << eval < even < int_<2>> >::value << '\n';
std::cerr << "even(3): " << eval < even < int_<3>> >::value << '\n';
std::cerr << "is_same: " << std::is_same < eval < int_ < 2 >> , int_ < 2 >> ::value << '\n';
typedef seq<int_<1>, int_<2>, int_<3>, int_<4>, int_<5>, int_<6>, int_<7>, int_<8>, int_<9>, int_<10>, int_<11>> sint;
std::cerr << eval < length < eval < map_t < sint, even > > > >::value << '\n';
std::cerr << eval < length < eval < filter_t < sint, even > > > >::value << '\n';
typedef eval<filter_t<sint, even>> test;
std::cerr << "first in even list: " << eval<car<test>>::value << '\n';
std::cerr << "second in even list: " << eval<car<eval<cdr<test>>>>::value << '\n';
std::cerr << "third in even list: " << eval<car<eval<cdr<eval<cdr<test>>>>>>::value << '\n';
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+Cgp0ZW1wbGF0ZSA8aW50IEk+IHVzaW5nIGludF8gPSBzdGQ6OmludGVncmFsX2NvbnN0YW50PGludCwgST47Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPiB1c2luZyBldmFsID0gdHlwZW5hbWUgVDo6dHlwZTsKCnRlbXBsYXRlPHR5cGVuYW1lLi4uIExpc3Q+CnN0cnVjdCBzZXEKewogICAgdXNpbmcgdHlwZSA9IHNlcTsKfTsKCnRlbXBsYXRlPHR5cGVuYW1lPiBzdHJ1Y3QgY2FyOwp0ZW1wbGF0ZTx0eXBlbmFtZSBDYXIsIHR5cGVuYW1lLi4uIENkcj4Kc3RydWN0IGNhcjwgc2VxPENhciwgQ2RyLi4uPj4KewogICAgdHlwZWRlZiBDYXIgdHlwZTsKfTsKCnRlbXBsYXRlPHR5cGVuYW1lPiBzdHJ1Y3QgY2RyOwp0ZW1wbGF0ZTx0eXBlbmFtZSBDYXIsIHR5cGVuYW1lLi4uIENkcj4Kc3RydWN0IGNkcjwgc2VxPENhciwgQ2RyLi4uPj4KewogICAgdHlwZWRlZiBzZXE8Q2RyLi4uPiB0eXBlOwp9OwoKCnRlbXBsYXRlIDx0eXBlbmFtZSwgdHlwZW5hbWU+IHN0cnVjdCBjb25zOwp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUuLi4gTD4Kc3RydWN0IGNvbnM8VCwgc2VxPEwuLi4+Pgp7CiAgICB0eXBlZGVmIHNlcTxULCBMLi4uPiB0eXBlOwp9OwoKLy90ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KLy9zdHJ1Y3QgY29uczxULCBzZXE8Pj4KLy97Ci8vICAgIHR5cGVkZWYgc2VxPFQ+IHR5cGU7Ci8vfTsKCnRlbXBsYXRlPHR5cGVuYW1lLCB0eXBlbmFtZT4gc3RydWN0IGNvbmNhdDsKdGVtcGxhdGUgPHR5cGVuYW1lLi4uIEFzLCB0eXBlbmFtZS4uLiBCcz4Kc3RydWN0IGNvbmNhdDxzZXE8QXMuLi4+LCBzZXE8QnMuLi4+Pgp7CiAgICB0eXBlZGVmIHNlcTxBcy4uLiwgQnMuLi4+IHR5cGU7Cn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZT4gc3RydWN0IGxlbmd0aDsKdGVtcGxhdGU8dHlwZW5hbWUuLi4gQXM+CnN0cnVjdCBsZW5ndGg8c2VxPEFzLi4uPj4KewogICAgdHlwZWRlZiBzdGQ6OmludGVncmFsX2NvbnN0YW50PHVuc2lnbmVkLCBzaXplb2YuLi4oQXMpPiB0eXBlOwp9OwoKdGVtcGxhdGU8dHlwZW5hbWU+CnN0cnVjdCBpc19lbXB0eQp7CiAgICB0eXBlZGVmIHN0ZDo6aW50ZWdyYWxfY29uc3RhbnQ8Ym9vbCwgZmFsc2U+IHR5cGU7Cn07Cgp0ZW1wbGF0ZTw+CnN0cnVjdCBpc19lbXB0eTxzZXE8Pj4KewogICAgdHlwZWRlZiBzdGQ6OmludGVncmFsX2NvbnN0YW50PGJvb2wsIHRydWU+IHR5cGU7Cn07Cgp0ZW1wbGF0ZTx0ZW1wbGF0ZTx0eXBlbmFtZS4uLiBBcmdzPiBjbGFzcyBGdW4sIHR5cGVuYW1lLi4uIEFyZ3M+CnN0cnVjdCBhcHBseQp7CiAgICB0eXBlZGVmIGV2YWw8RnVuPEFyZ3MuLi4+PiB0eXBlOwp9OwoKCnRlbXBsYXRlPHR5cGVuYW1lIEIsIHR5cGVuYW1lIEMsIHR5cGVuYW1lIEE+IHN0cnVjdCBjb25kOwp0ZW1wbGF0ZTx0eXBlbmFtZSBDLCB0eXBlbmFtZSBBPgpzdHJ1Y3QgY29uZDxzdGQ6OnRydWVfdHlwZSwgQywgQT4KewogICAgdHlwZWRlZiBDIHR5cGU7Cn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBDLCB0eXBlbmFtZSBBPgpzdHJ1Y3QgY29uZDxzdGQ6OmZhbHNlX3R5cGUsIEMsIEE+CnsKICAgIHR5cGVkZWYgQSB0eXBlOwp9OwoKCi8vdGVtcGxhdGU8dHlwZW5hbWUsIHR5cGVuYW1lPiBzdHJ1Y3QgbWFwOwoKLy90ZW1wbGF0ZTx0eXBlbmFtZSBBLCB0eXBlbmFtZS4uLiBBcywgdGVtcGxhdGU8dHlwZW5hbWUgQT4gY2xhc3MgRj4KLy9zdHJ1Y3QgbWFwPHNlcTxBLCBBcy4uLj4sIEY+Ci8vewovLyAgICAvL3R5cGVkZWYgc2VxPGV2YWw8RjxBPj4uLi4+IHR5cGU7Ci8vICAgIHR5cGVkZWYgY29ucyA8IGV2YWwgPCBGIDwgQSA+ID4KLy8gICAgICAgICAgICAgICAgICwgbWFwIDwgc2VxIDwgQXMuLi4gPiAsIEYgPgovLyAgICAgICAgICAgICAgICAgPiB0eXBlOwovL307Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgUywgdGVtcGxhdGU8dHlwZW5hbWUgQj4gY2xhc3MgRj4gc3RydWN0IG1hcF90OwoKLy90ZW1wbGF0ZSA8dGVtcGxhdGUgPHR5cGVuYW1lIEI+IGNsYXNzIEYsIHR5cGVuYW1lLi4uIEVzPgp0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4gRXMsIHRlbXBsYXRlIDx0eXBlbmFtZSBCPiBjbGFzcyBGPgpzdHJ1Y3QgbWFwX3QgPHNlcTxFcy4uLj4sIEYgPgp7CiAgICB0eXBlZGVmIHR5cGVuYW1lIGNhcjxzZXE8RXMuLi4+Pjo6dHlwZSBDYXI7CiAgICB0eXBlZGVmIHR5cGVuYW1lIGNkcjxzZXE8RXMuLi4+Pjo6dHlwZSBDZHI7CiAgICB0eXBlZGVmIGV2YWw8IGNvbnMgPCBldmFsIDwgRiA8IENhciA+ID4KICAgICAgICAgICAgICAgICAsIGV2YWw8IG1hcF90IDwgQ2RyLCBGID4gPgogICAgICAgICAgICAgICAgID4gPiB0eXBlOwp9OwoKdGVtcGxhdGUgPHRlbXBsYXRlIDx0eXBlbmFtZSBCPiBjbGFzcyBGPgpzdHJ1Y3QgbWFwX3QgPHNlcTw+LCBGID4KewogICAgdHlwZWRlZiBzZXE8PiB0eXBlOwp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFMsIHRlbXBsYXRlPHR5cGVuYW1lIEI+IGNsYXNzIEY+IHN0cnVjdCBmaWx0ZXJfdDsKCi8vdGVtcGxhdGUgPHRlbXBsYXRlIDx0eXBlbmFtZSBCPiBjbGFzcyBGLCB0eXBlbmFtZS4uLiBFcz4KdGVtcGxhdGUgPHR5cGVuYW1lLi4uIEVzLCB0ZW1wbGF0ZSA8dHlwZW5hbWUgQj4gY2xhc3MgRj4Kc3RydWN0IGZpbHRlcl90IDxzZXE8RXMuLi4+LCBGID4KewogICAgdHlwZWRlZiB0eXBlbmFtZSBjYXI8c2VxPEVzLi4uPj46OnR5cGUgQ2FyOwogICAgdHlwZWRlZiB0eXBlbmFtZSBjZHI8c2VxPEVzLi4uPj46OnR5cGUgQ2RyOwogICAgdHlwZWRlZiBldmFsPCBjb25kIDwgZXZhbCA8IEYgPCBDYXIgPiA+CiAgICAgICAgICAgICAgICAgICAgICAgLCBldmFsIDwgY29ucyA8IENhciwgZXZhbDwgZmlsdGVyX3QgPCBDZHIsIEYgPiA+ID4gPgogICAgICAgICAgICAgICAgICAgICAgICwgZXZhbCA8IGZpbHRlcl90IDwgQ2RyLCBGID4gPgogICAgICAgICAgICAgICAgICAgICAgID4gPiB0eXBlOwp9OwoKdGVtcGxhdGUgPHRlbXBsYXRlIDx0eXBlbmFtZSBCPiBjbGFzcyBGPgpzdHJ1Y3QgZmlsdGVyX3QgPHNlcTw+LCBGID4KewogICAgdHlwZWRlZiBzZXE8PiB0eXBlOwp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgQT4gc3RydWN0IGV2ZW47Cgp0ZW1wbGF0ZTxpbnQgST4Kc3RydWN0IGV2ZW48c3RkOjppbnRlZ3JhbF9jb25zdGFudDxpbnQsIEk+ID4KewogICAgdHlwZWRlZiBzdGQ6OmludGVncmFsX2NvbnN0YW50PGJvb2wsIEkgJSAyID09IDA+IHR5cGU7Cn07CgoKLy90ZW1wbGF0ZTx0eXBlbmFtZT4gc3RydWN0IGNvbnN0YW50OwovL3RlbXBsYXRlPHR5cGVuYW1lIFQ+Ci8vc3RydWN0IGNvbnN0YW50PFQ+Ci8vewovLyAgICB0eXBlZGVmIHN0ZDo6aW50ZWdyYWxfY29uc3RhbnQ8Ym9vbCwgZmFsc2U+IHR5cGU7Ci8vfTsKCgp0eXBlZGVmIHNlcTxpbnRfPDE+LCBpbnRfPDI+LCBpbnRfPDM+ID4gczE7CnR5cGVkZWYgc2VxPGludF88Nz4sIGludF88NT4sIGludF88OT4gPiBzMjsKdHlwZWRlZiBzZXE8aW50XzwxPiwgczIsIGludF88MTc+LCBzMSA+IHMzOwp0eXBlZGVmIHNlcTw+IGVtcHR5Owp0eXBlZGVmIHNlcTxpbnRfPDE+PiBzMDsKCnRlbXBsYXRlPHR5cGVuYW1lIFNlcT4gdXNpbmcgY29uY2F0X2ZpeCA9IGFwcGx5PGNvbmNhdCwgczIsIFNlcT47CgoKaW50IG1haW4oKQp7CgogICAgc3RkOjpjZXJyIDw8IGV2YWwgPCBsZW5ndGggPCBldmFsIDwgYXBwbHkgPCBjb25jYXQsIHMxLCBzMyA+PiA+PiA6OnZhbHVlIDw8ICdcbic7CiAgICBzdGQ6OmNlcnIgPDwgZXZhbCA8IGxlbmd0aCA8IGV2YWwgPCBjb25jYXRfZml4IDwgczMgPj4gPj4gOjp2YWx1ZSA8PCAnXG4nOwogICAgc3RkOjpjZXJyIDw8IGV2YWwgPCBhcHBseSA8IGxlbmd0aCwgZW1wdHk+ID46OnZhbHVlIDw8ICdcbic7CiAgICBzdGQ6OmNlcnIgPDwgZXZhbCA8IGxlbmd0aCA8IGV2YWwgPCBjb25jYXQgPCBzMSwgczMgPj4gPj4gOjp2YWx1ZSA8PCAnXG4nOwogICAgc3RkOjpjZXJyIDw8ICJldmVuKDIpOiAiIDw8IGV2YWwgPCBldmVuIDwgaW50XzwyPj4gPjo6dmFsdWUgPDwgJ1xuJzsKICAgIHN0ZDo6Y2VyciA8PCAiZXZlbigzKTogIiA8PCBldmFsIDwgZXZlbiA8IGludF88Mz4+ID46OnZhbHVlIDw8ICdcbic7CgogICAgc3RkOjpjZXJyIDw8ICJpc19zYW1lOiAiIDw8IHN0ZDo6aXNfc2FtZSA8IGV2YWwgPCBpbnRfIDwgMiA+PiAsIGludF8gPCAyID4+IDo6dmFsdWUgPDwgJ1xuJzsKCiAgICB0eXBlZGVmIHNlcTxpbnRfPDE+LCBpbnRfPDI+LCBpbnRfPDM+LCBpbnRfPDQ+LCBpbnRfPDU+LCBpbnRfPDY+LCBpbnRfPDc+LCBpbnRfPDg+LCBpbnRfPDk+LCBpbnRfPDEwPiwgaW50XzwxMT4+IHNpbnQ7CiAgICBzdGQ6OmNlcnIgPDwgZXZhbCA8IGxlbmd0aCA8IGV2YWwgPCBtYXBfdCA8IHNpbnQsIGV2ZW4gPiA+ID4gPjo6dmFsdWUgPDwgJ1xuJzsKICAgIHN0ZDo6Y2VyciA8PCBldmFsIDwgbGVuZ3RoIDwgZXZhbCA8IGZpbHRlcl90IDwgc2ludCwgZXZlbiA+ID4gPiA+Ojp2YWx1ZSA8PCAnXG4nOwogICAgdHlwZWRlZiBldmFsPGZpbHRlcl90PHNpbnQsIGV2ZW4+PiB0ZXN0OwoKICAgIHN0ZDo6Y2VyciA8PCAiZmlyc3QgaW4gZXZlbiBsaXN0OiAiIDw8IGV2YWw8Y2FyPHRlc3Q+Pjo6dmFsdWUgPDwgJ1xuJzsKICAgIHN0ZDo6Y2VyciA8PCAic2Vjb25kIGluIGV2ZW4gbGlzdDogIiA8PCBldmFsPGNhcjxldmFsPGNkcjx0ZXN0Pj4+Pjo6dmFsdWUgPDwgJ1xuJzsKICAgIHN0ZDo6Y2VyciA8PCAidGhpcmQgaW4gZXZlbiBsaXN0OiAiIDw8IGV2YWw8Y2FyPGV2YWw8Y2RyPGV2YWw8Y2RyPHRlc3Q+Pj4+Pj46OnZhbHVlIDw8ICdcbic7CiAgICByZXR1cm4gMDsKfQ==