#include <iostream>
using namespace std;
template <typename ...Args>
struct type_list
{};
using empty_list = type_list<>;
// identity
template<typename T>
struct identity
{
using type = T;
};
// is_typelist
template<typename T>
struct is_typelist: std::false_type
{};
template<typename ...Args>
struct is_typelist<type_list<Args...>>: std::true_type
{};
template<typename T>
struct check_typelist
{
using type = void;
static constexpr void *value = nullptr;
static_assert(is_typelist<T>::value, "T is not a type_list!");
};
// indexof
namespace internal {
template<typename T, typename V, std::int64_t index>
struct typelist_indexof_helper: check_typelist<T>
{};
template<typename H, typename ...T, typename V, std::int64_t index>
struct typelist_indexof_helper<type_list<H, T...>, V, index>:
std::conditional<std::is_same<H, V>::value,
std::integral_constant<std::int64_t, index>,
typelist_indexof_helper<type_list<T...>, V, index + 1>
>::type
{};
template<typename V, std::int64_t index>
struct typelist_indexof_helper<empty_list, V, index>: std::integral_constant<std::int64_t, -1>
{};
}
template<typename T, typename V>
using typelist_indexof = ::internal::typelist_indexof_helper<T, V, 0>;
template<typename T, typename V>
struct typelist_exists: std::integral_constant<bool, typelist_indexof<T, V>::value >= 0>
{};
// remove_duplicates
namespace internal {
template<typename P, typename T>
struct typelist_remove_duplicates_helper: check_typelist<T>
{};
template<typename ...P, typename H, typename ...T>
struct typelist_remove_duplicates_helper<type_list<P...>, type_list<H, T...>>:
std::conditional<typelist_exists<type_list<T...>, H>::value,
typelist_remove_duplicates_helper<type_list<P...>, type_list<T...>>,
typelist_remove_duplicates_helper<type_list<P..., H>, type_list<T...>>
>::type
{};
template<typename ...P>
struct typelist_remove_duplicates_helper<type_list<P...>, empty_list>: identity<type_list<P...>>
{};
}
template<typename T>
using typelist_remove_duplicates = ::internal::typelist_remove_duplicates_helper<empty_list, T>;
template<typename ...Args>
struct has_no_duplicates: std::integral_constant<bool, std::is_same<type_list<Args...>,
typename typelist_remove_duplicates<type_list<Args...>>::type>::value>
{};
int main() {
std::cout << has_no_duplicates<int, double, char>::value << std::endl;
std::cout << has_no_duplicates<int, double, int, char>::value << std::endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKdGVtcGxhdGUgPHR5cGVuYW1lIC4uLkFyZ3M+CnN0cnVjdCB0eXBlX2xpc3QKe307Cgp1c2luZyBlbXB0eV9saXN0ID0gdHlwZV9saXN0PD47CgovLyBpZGVudGl0eQp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpzdHJ1Y3QgaWRlbnRpdHkKewogICAgdXNpbmcgdHlwZSA9IFQ7Cn07CgovLyBpc190eXBlbGlzdAp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpzdHJ1Y3QgaXNfdHlwZWxpc3Q6IHN0ZDo6ZmFsc2VfdHlwZQp7fTsKCnRlbXBsYXRlPHR5cGVuYW1lIC4uLkFyZ3M+CnN0cnVjdCBpc190eXBlbGlzdDx0eXBlX2xpc3Q8QXJncy4uLj4+OiBzdGQ6OnRydWVfdHlwZQp7fTsKCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnN0cnVjdCBjaGVja190eXBlbGlzdAp7CiAgICB1c2luZyB0eXBlID0gdm9pZDsKICAgIHN0YXRpYyBjb25zdGV4cHIgdm9pZCAqdmFsdWUgPSBudWxscHRyOwogICAgc3RhdGljX2Fzc2VydChpc190eXBlbGlzdDxUPjo6dmFsdWUsICJUIGlzIG5vdCBhIHR5cGVfbGlzdCEiKTsKfTsKCi8vIGluZGV4b2YKbmFtZXNwYWNlIGludGVybmFsIHsKCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFYsIHN0ZDo6aW50NjRfdCBpbmRleD4Kc3RydWN0IHR5cGVsaXN0X2luZGV4b2ZfaGVscGVyOiBjaGVja190eXBlbGlzdDxUPgp7fTsKCnRlbXBsYXRlPHR5cGVuYW1lIEgsIHR5cGVuYW1lIC4uLlQsIHR5cGVuYW1lIFYsIHN0ZDo6aW50NjRfdCBpbmRleD4Kc3RydWN0IHR5cGVsaXN0X2luZGV4b2ZfaGVscGVyPHR5cGVfbGlzdDxILCBULi4uPiwgViwgaW5kZXg+OgogICAgICAgIHN0ZDo6Y29uZGl0aW9uYWw8c3RkOjppc19zYW1lPEgsIFY+Ojp2YWx1ZSwKICAgICAgICAgICAgc3RkOjppbnRlZ3JhbF9jb25zdGFudDxzdGQ6OmludDY0X3QsIGluZGV4PiwKICAgICAgICAgICAgdHlwZWxpc3RfaW5kZXhvZl9oZWxwZXI8dHlwZV9saXN0PFQuLi4+LCBWLCBpbmRleCArIDE+CiAgICAgICAgPjo6dHlwZQp7fTsKCnRlbXBsYXRlPHR5cGVuYW1lIFYsIHN0ZDo6aW50NjRfdCBpbmRleD4Kc3RydWN0IHR5cGVsaXN0X2luZGV4b2ZfaGVscGVyPGVtcHR5X2xpc3QsIFYsIGluZGV4Pjogc3RkOjppbnRlZ3JhbF9jb25zdGFudDxzdGQ6OmludDY0X3QsIC0xPgp7fTsKCn0KCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFY+CnVzaW5nIHR5cGVsaXN0X2luZGV4b2YgPSA6OmludGVybmFsOjp0eXBlbGlzdF9pbmRleG9mX2hlbHBlcjxULCBWLCAwPjsKCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFY+CnN0cnVjdCB0eXBlbGlzdF9leGlzdHM6IHN0ZDo6aW50ZWdyYWxfY29uc3RhbnQ8Ym9vbCwgdHlwZWxpc3RfaW5kZXhvZjxULCBWPjo6dmFsdWUgPj0gMD4Ke307CgovLyByZW1vdmVfZHVwbGljYXRlcwpuYW1lc3BhY2UgaW50ZXJuYWwgewoKdGVtcGxhdGU8dHlwZW5hbWUgUCwgdHlwZW5hbWUgVD4Kc3RydWN0IHR5cGVsaXN0X3JlbW92ZV9kdXBsaWNhdGVzX2hlbHBlcjogY2hlY2tfdHlwZWxpc3Q8VD4Ke307Cgp0ZW1wbGF0ZTx0eXBlbmFtZSAuLi5QLCB0eXBlbmFtZSBILCB0eXBlbmFtZSAuLi5UPgpzdHJ1Y3QgdHlwZWxpc3RfcmVtb3ZlX2R1cGxpY2F0ZXNfaGVscGVyPHR5cGVfbGlzdDxQLi4uPiwgdHlwZV9saXN0PEgsIFQuLi4+PjoKICAgICAgICBzdGQ6OmNvbmRpdGlvbmFsPHR5cGVsaXN0X2V4aXN0czx0eXBlX2xpc3Q8VC4uLj4sIEg+Ojp2YWx1ZSwKICAgICAgICAgICAgdHlwZWxpc3RfcmVtb3ZlX2R1cGxpY2F0ZXNfaGVscGVyPHR5cGVfbGlzdDxQLi4uPiwgdHlwZV9saXN0PFQuLi4+PiwKICAgICAgICAgICAgdHlwZWxpc3RfcmVtb3ZlX2R1cGxpY2F0ZXNfaGVscGVyPHR5cGVfbGlzdDxQLi4uLCBIPiwgdHlwZV9saXN0PFQuLi4+PgogICAgICAgID46OnR5cGUKe307Cgp0ZW1wbGF0ZTx0eXBlbmFtZSAuLi5QPgpzdHJ1Y3QgdHlwZWxpc3RfcmVtb3ZlX2R1cGxpY2F0ZXNfaGVscGVyPHR5cGVfbGlzdDxQLi4uPiwgZW1wdHlfbGlzdD46IGlkZW50aXR5PHR5cGVfbGlzdDxQLi4uPj4Ke307Cgp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgp1c2luZyB0eXBlbGlzdF9yZW1vdmVfZHVwbGljYXRlcyA9IDo6aW50ZXJuYWw6OnR5cGVsaXN0X3JlbW92ZV9kdXBsaWNhdGVzX2hlbHBlcjxlbXB0eV9saXN0LCBUPjsKCgp0ZW1wbGF0ZTx0eXBlbmFtZSAuLi5BcmdzPgpzdHJ1Y3QgaGFzX25vX2R1cGxpY2F0ZXM6IHN0ZDo6aW50ZWdyYWxfY29uc3RhbnQ8Ym9vbCwgc3RkOjppc19zYW1lPHR5cGVfbGlzdDxBcmdzLi4uPiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlbmFtZSB0eXBlbGlzdF9yZW1vdmVfZHVwbGljYXRlczx0eXBlX2xpc3Q8QXJncy4uLj4+Ojp0eXBlPjo6dmFsdWU+Cnt9OwoKCgppbnQgbWFpbigpIHsKICAgIHN0ZDo6Y291dCA8PCBoYXNfbm9fZHVwbGljYXRlczxpbnQsIGRvdWJsZSwgY2hhcj46OnZhbHVlIDw8IHN0ZDo6ZW5kbDsKICAgIHN0ZDo6Y291dCA8PCBoYXNfbm9fZHVwbGljYXRlczxpbnQsIGRvdWJsZSwgaW50LCBjaGFyPjo6dmFsdWUgPDwgc3RkOjplbmRsOwoJcmV0dXJuIDA7Cn0=