#include <type_traits>
namespace tmpalg {
template <typename... T> struct type_list;
template <typename T> using identity = T;
template <typename TL>
using size = std::integral_constant<int, -1>; // size::value contains the number
// of types in type_list<T...>
template <typename TL, int N>
using at = void; // Nth type in TL=type_list<T...> (zero based)
template <typename TL, template <typename> class F>
using transform = void; // type_list<T...> becomes type_list<F<T>...>
template <typename TL, template <typename> class Pred=identity>
using filter = void; // returns a type_list where for every element T
// Pred<T>::value == true holds
template <typename TL, template <typename> class Pred=identity>
using all_of = std::false_type; // all_of<...>::value == true if
// Pred<T>::value == true for all T in TL
template <typename TL, template <typename> class Pred=identity>
using any_of = std::false_type; // all_of<...>::value == true if
// Pred<T>::value == true for at least one T in TL
template <typename TL, template <typename> class Pred=identity>
using none_of = std::false_type; // all_of<...>::value == true if
// Pred<T>::value == true for no T in TL
}
template <typename T> struct test;
int main()
{
using namespace tmpalg;
using list = type_list<int /*0*/, char /*1*/, long /*2*/,
float /*3*/, short /*4*/, void /*5*/,
double /*6*/, int /*7*/>;
static_assert(size<list>::value == 8, "size fails");
static_assert(size<type_list<> >::value == 0, "size fails");
static_assert(std::is_same<at<list, 3>, float>::value, "at fails");
static_assert(std::is_same<transform<list, identity>, list>::value, "transform fails");
static_assert(std::is_same<at<transform<list, test>, 1>, test<char> >::value, "transform fails");
static_assert(size<transform<list, test> >::value == size<list>::value, "transform fails");
static_assert(size<filter<list, std::is_integral> >::value == size<list>::value - 3, "filter fails");
static_assert(all_of<filter<list, std::is_integral>, std::is_integral>::value, "all_of fails");
static_assert(!all_of<list, std::is_integral>::value, "all_of fails");
static_assert(any_of<list, std::is_integral>::value, "any_of fails");
static_assert(!any_of<list, std::is_pointer>::value, "any_of fails");
static_assert(none_of<list, std::is_pointer>::value, "none_of fails");
static_assert(!none_of<list, std::is_fundamental>::value, "none_of fails");
/* these lines should not compile (if you remove the comments) */
//using X = at<999, list>;
//using Y = at<0, void>;
//auto Z = size<void>::value;
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgoKbmFtZXNwYWNlIHRtcGFsZyB7CiAgdGVtcGxhdGUgPHR5cGVuYW1lLi4uIFQ+IHN0cnVjdCB0eXBlX2xpc3Q7CiAgdGVtcGxhdGUgPHR5cGVuYW1lIFQ+IHVzaW5nIGlkZW50aXR5ID0gVDsKCiAgdGVtcGxhdGUgPHR5cGVuYW1lIFRMPgogIHVzaW5nIHNpemUgPSBzdGQ6OmludGVncmFsX2NvbnN0YW50PGludCwgLTE+OyAvLyBzaXplOjp2YWx1ZSBjb250YWlucyB0aGUgbnVtYmVyCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9mIHR5cGVzIGluIHR5cGVfbGlzdDxULi4uPgoKICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVEwsIGludCBOPgogIHVzaW5nIGF0ID0gdm9pZDsgLy8gTnRoIHR5cGUgaW4gVEw9dHlwZV9saXN0PFQuLi4+ICAoemVybyBiYXNlZCkKCiAgdGVtcGxhdGUgPHR5cGVuYW1lIFRMLCB0ZW1wbGF0ZSA8dHlwZW5hbWU+IGNsYXNzIEY+CiAgdXNpbmcgdHJhbnNmb3JtID0gdm9pZDsgLy8gdHlwZV9saXN0PFQuLi4+IGJlY29tZXMgdHlwZV9saXN0PEY8VD4uLi4+CgogIHRlbXBsYXRlIDx0eXBlbmFtZSBUTCwgdGVtcGxhdGUgPHR5cGVuYW1lPiBjbGFzcyBQcmVkPWlkZW50aXR5PgogIHVzaW5nIGZpbHRlciA9IHZvaWQ7IC8vIHJldHVybnMgYSB0eXBlX2xpc3Qgd2hlcmUgZm9yIGV2ZXJ5IGVsZW1lbnQgVAogICAgICAgICAgICAgICAgICAgICAgIC8vIFByZWQ8VD46OnZhbHVlID09IHRydWUgaG9sZHMgCgogIHRlbXBsYXRlIDx0eXBlbmFtZSBUTCwgdGVtcGxhdGUgPHR5cGVuYW1lPiBjbGFzcyBQcmVkPWlkZW50aXR5PgogIHVzaW5nIGFsbF9vZiA9IHN0ZDo6ZmFsc2VfdHlwZTsgLy8gYWxsX29mPC4uLj46OnZhbHVlID09IHRydWUgaWYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFByZWQ8VD46OnZhbHVlID09IHRydWUgZm9yIGFsbCBUIGluIFRMCgogIHRlbXBsYXRlIDx0eXBlbmFtZSBUTCwgdGVtcGxhdGUgPHR5cGVuYW1lPiBjbGFzcyBQcmVkPWlkZW50aXR5PgogIHVzaW5nIGFueV9vZiA9IHN0ZDo6ZmFsc2VfdHlwZTsgLy8gYWxsX29mPC4uLj46OnZhbHVlID09IHRydWUgaWYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFByZWQ8VD46OnZhbHVlID09IHRydWUgZm9yIGF0IGxlYXN0IG9uZSBUIGluIFRMCgogIHRlbXBsYXRlIDx0eXBlbmFtZSBUTCwgdGVtcGxhdGUgPHR5cGVuYW1lPiBjbGFzcyBQcmVkPWlkZW50aXR5PgogIHVzaW5nIG5vbmVfb2YgPSBzdGQ6OmZhbHNlX3R5cGU7IC8vIGFsbF9vZjwuLi4+Ojp2YWx1ZSA9PSB0cnVlIGlmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUHJlZDxUPjo6dmFsdWUgPT0gdHJ1ZSBmb3Igbm8gVCBpbiBUTAp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4gc3RydWN0IHRlc3Q7CgppbnQgbWFpbigpCnsKICB1c2luZyBuYW1lc3BhY2UgdG1wYWxnOwoKICB1c2luZyBsaXN0ID0gdHlwZV9saXN0PGludCAvKjAqLywgY2hhciAvKjEqLywgbG9uZyAvKjIqLywKICAgICAgICAgICAgICAgICAgICAgICAgIGZsb2F0IC8qMyovLCBzaG9ydCAvKjQqLywgdm9pZCAvKjUqLywKICAgICAgICAgICAgICAgICAgICAgICAgIGRvdWJsZSAvKjYqLywgaW50IC8qNyovPjsKICBzdGF0aWNfYXNzZXJ0KHNpemU8bGlzdD46OnZhbHVlID09IDgsICJzaXplIGZhaWxzIik7CiAgc3RhdGljX2Fzc2VydChzaXplPHR5cGVfbGlzdDw+ID46OnZhbHVlID09IDAsICJzaXplIGZhaWxzIik7CiAgc3RhdGljX2Fzc2VydChzdGQ6OmlzX3NhbWU8YXQ8bGlzdCwgMz4sIGZsb2F0Pjo6dmFsdWUsICJhdCBmYWlscyIpOwogIHN0YXRpY19hc3NlcnQoc3RkOjppc19zYW1lPHRyYW5zZm9ybTxsaXN0LCBpZGVudGl0eT4sIGxpc3Q+Ojp2YWx1ZSwgInRyYW5zZm9ybSBmYWlscyIpOyAgCiAgc3RhdGljX2Fzc2VydChzdGQ6OmlzX3NhbWU8YXQ8dHJhbnNmb3JtPGxpc3QsIHRlc3Q+LCAxPiwgdGVzdDxjaGFyPiA+Ojp2YWx1ZSwgInRyYW5zZm9ybSBmYWlscyIpOwogIHN0YXRpY19hc3NlcnQoc2l6ZTx0cmFuc2Zvcm08bGlzdCwgdGVzdD4gPjo6dmFsdWUgPT0gc2l6ZTxsaXN0Pjo6dmFsdWUsICJ0cmFuc2Zvcm0gZmFpbHMiKTsKICBzdGF0aWNfYXNzZXJ0KHNpemU8ZmlsdGVyPGxpc3QsIHN0ZDo6aXNfaW50ZWdyYWw+ID46OnZhbHVlID09IHNpemU8bGlzdD46OnZhbHVlIC0gMywgImZpbHRlciBmYWlscyIpOwogIHN0YXRpY19hc3NlcnQoYWxsX29mPGZpbHRlcjxsaXN0LCBzdGQ6OmlzX2ludGVncmFsPiwgc3RkOjppc19pbnRlZ3JhbD46OnZhbHVlLCAiYWxsX29mIGZhaWxzIik7CiAgc3RhdGljX2Fzc2VydCghYWxsX29mPGxpc3QsIHN0ZDo6aXNfaW50ZWdyYWw+Ojp2YWx1ZSwgImFsbF9vZiBmYWlscyIpOwogIHN0YXRpY19hc3NlcnQoYW55X29mPGxpc3QsIHN0ZDo6aXNfaW50ZWdyYWw+Ojp2YWx1ZSwgImFueV9vZiBmYWlscyIpOwogIHN0YXRpY19hc3NlcnQoIWFueV9vZjxsaXN0LCBzdGQ6OmlzX3BvaW50ZXI+Ojp2YWx1ZSwgImFueV9vZiBmYWlscyIpOwogIHN0YXRpY19hc3NlcnQobm9uZV9vZjxsaXN0LCBzdGQ6OmlzX3BvaW50ZXI+Ojp2YWx1ZSwgIm5vbmVfb2YgZmFpbHMiKTsKICBzdGF0aWNfYXNzZXJ0KCFub25lX29mPGxpc3QsIHN0ZDo6aXNfZnVuZGFtZW50YWw+Ojp2YWx1ZSwgIm5vbmVfb2YgZmFpbHMiKTsKCiAgLyogdGhlc2UgbGluZXMgc2hvdWxkIG5vdCBjb21waWxlIChpZiB5b3UgcmVtb3ZlIHRoZSBjb21tZW50cykgKi8KICAvL3VzaW5nIFggPSBhdDw5OTksIGxpc3Q+OwogIC8vdXNpbmcgWSA9IGF0PDAsIHZvaWQ+OwogIC8vYXV0byBaID0gc2l6ZTx2b2lkPjo6dmFsdWU7Cn0K