#include <type_traits>
#include <cassert>
#include <iostream>
template<typename...>
struct toRecursiveList;
//a recursive list already
template<template <typename...> class Pack, typename H, typename... T>
struct toRecursiveList<Pack<H, Pack<T...>>>
{
using type = Pack<H, Pack<T...>>;
};
//several elements
template<template <typename...> class Pack, typename H, typename... T>
struct toRecursiveList<Pack<H, T...>>
{
using type = Pack<H, Pack<T...>>;
};
//one element
template<template <typename...> class Pack, typename H>
struct toRecursiveList<Pack<H> >
{
using type = Pack<H, Pack<>>;
};
//empty
template<template <typename...> class Pack>
struct toRecursiveList<Pack<>>
{
using type = Pack<>;
};
//missing pack
template<typename H, typename... T>
struct toRecursiveList<H, T...>
{
template<typename...>
struct Pack;
using type = Pack<H, Pack<T...>>;
};
//base case - guarantees an initial recursive list
template <template <typename...> class F, typename... L>
struct any_n :
any_n<F, typename toRecursiveList<L>::type...>
{};
//main recursion
template
<
template <typename...> class F,
template <typename...> class... Pack, typename... H, typename... T
>
struct any_n <F, Pack <H, T>...> : //two elements each, no need for double pack expansion on T
std::conditional<F<H...>{}, std::true_type, any_n<F, typename toRecursiveList<T>::type...>>::type
// ^ ensures a recursive list is passed onto the next recursion step
{};
//recursion guard
template
<
template <typename...> class F,
template <typename...> class Pack, typename... T
>
struct any_n<F, Pack <>, T...> :
std::false_type
{};
template<typename...>
struct is_same_n;
template<typename A, typename B, typename... T>
struct is_same_n<A, B, T...> :
std::conditional<std::is_same<A, B>{}, is_same_n<B, T...>, std::false_type>::type
{};
template<typename A, typename B>
struct is_same_n<A, B> :
std::is_same<A, B>
{};
template<typename...>
struct Pack;
int main()
{
typedef Pack<int, float, double, void> A;
typedef Pack<void, float, double, void> B;
typedef Pack<float, bool, double, void> C;
typedef Pack<float, int, char, void> D;
typedef Pack<bool, char, void, double> E;
assert((any_n <is_same_n, A, B>())); // true
assert((any_n <is_same_n, A, B, C>())); // true
assert((any_n <is_same_n, A, B, C, D>())); // true
assert(!(any_n <is_same_n, A, B, C, D, E>())); // false
std::cout << "PASSED!" << std::endl;
return 0;
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8Y2Fzc2VydD4KI2luY2x1ZGUgPGlvc3RyZWFtPgoKdGVtcGxhdGU8dHlwZW5hbWUuLi4+CnN0cnVjdCB0b1JlY3Vyc2l2ZUxpc3Q7CgovL2EgcmVjdXJzaXZlIGxpc3QgYWxyZWFkeQp0ZW1wbGF0ZTx0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4+IGNsYXNzIFBhY2ssIHR5cGVuYW1lIEgsIHR5cGVuYW1lLi4uIFQ+CnN0cnVjdCB0b1JlY3Vyc2l2ZUxpc3Q8UGFjazxILCBQYWNrPFQuLi4+Pj4KewogICAgdXNpbmcgdHlwZSA9IFBhY2s8SCwgUGFjazxULi4uPj47Cn07CgovL3NldmVyYWwgZWxlbWVudHMKdGVtcGxhdGU8dGVtcGxhdGUgPHR5cGVuYW1lLi4uPiBjbGFzcyBQYWNrLCB0eXBlbmFtZSBILCB0eXBlbmFtZS4uLiBUPgpzdHJ1Y3QgdG9SZWN1cnNpdmVMaXN0PFBhY2s8SCwgVC4uLj4+CnsKICAgIHVzaW5nIHR5cGUgPSBQYWNrPEgsIFBhY2s8VC4uLj4+Owp9OwoKLy9vbmUgZWxlbWVudAp0ZW1wbGF0ZTx0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4+IGNsYXNzIFBhY2ssIHR5cGVuYW1lIEg+CnN0cnVjdCB0b1JlY3Vyc2l2ZUxpc3Q8UGFjazxIPiA+CnsKICAgIHVzaW5nIHR5cGUgPSBQYWNrPEgsIFBhY2s8Pj47Cn07CgovL2VtcHR5CnRlbXBsYXRlPHRlbXBsYXRlIDx0eXBlbmFtZS4uLj4gY2xhc3MgUGFjaz4Kc3RydWN0IHRvUmVjdXJzaXZlTGlzdDxQYWNrPD4+CnsKICAgIHVzaW5nIHR5cGUgPSBQYWNrPD47Cn07CgovL21pc3NpbmcgcGFjawp0ZW1wbGF0ZTx0eXBlbmFtZSBILCB0eXBlbmFtZS4uLiBUPgpzdHJ1Y3QgdG9SZWN1cnNpdmVMaXN0PEgsIFQuLi4+CnsKICAgIHRlbXBsYXRlPHR5cGVuYW1lLi4uPgogICAgc3RydWN0IFBhY2s7CiAgICB1c2luZyB0eXBlID0gUGFjazxILCBQYWNrPFQuLi4+PjsKfTsKCi8vYmFzZSBjYXNlIC0gZ3VhcmFudGVlcyBhbiBpbml0aWFsIHJlY3Vyc2l2ZSBsaXN0CnRlbXBsYXRlIDx0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4+IGNsYXNzIEYsIHR5cGVuYW1lLi4uIEw+CnN0cnVjdCBhbnlfbiA6CiAgICAgICAgYW55X248RiwgdHlwZW5hbWUgdG9SZWN1cnNpdmVMaXN0PEw+Ojp0eXBlLi4uPgp7fTsKCi8vbWFpbiByZWN1cnNpb24KdGVtcGxhdGUKPAogICAgdGVtcGxhdGUgPHR5cGVuYW1lLi4uPiBjbGFzcyBGLAogICAgdGVtcGxhdGUgPHR5cGVuYW1lLi4uPiBjbGFzcy4uLiBQYWNrLCB0eXBlbmFtZS4uLiBILCB0eXBlbmFtZS4uLiBUCj4Kc3RydWN0IGFueV9uIDxGLCBQYWNrIDxILCBUPi4uLj4gOiAvL3R3byBlbGVtZW50cyBlYWNoLCBubyBuZWVkIGZvciBkb3VibGUgcGFjayBleHBhbnNpb24gb24gVAogICAgc3RkOjpjb25kaXRpb25hbDxGPEguLi4+e30sIHN0ZDo6dHJ1ZV90eXBlLCBhbnlfbjxGLCB0eXBlbmFtZSB0b1JlY3Vyc2l2ZUxpc3Q8VD46OnR5cGUuLi4+Pjo6dHlwZQogICAgLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBeIGVuc3VyZXMgYSByZWN1cnNpdmUgbGlzdCBpcyBwYXNzZWQgb250byB0aGUgbmV4dCByZWN1cnNpb24gc3RlcAp7fTsKCi8vcmVjdXJzaW9uIGd1YXJkCnRlbXBsYXRlCjwKICAgIHRlbXBsYXRlIDx0eXBlbmFtZS4uLj4gY2xhc3MgRiwKICAgIHRlbXBsYXRlIDx0eXBlbmFtZS4uLj4gY2xhc3MgUGFjaywgdHlwZW5hbWUuLi4gVAo+CnN0cnVjdCBhbnlfbjxGLCBQYWNrIDw+LCBULi4uPiA6CiAgICAgICAgc3RkOjpmYWxzZV90eXBlCnt9OwoKdGVtcGxhdGU8dHlwZW5hbWUuLi4+CnN0cnVjdCBpc19zYW1lX247Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBBLCB0eXBlbmFtZSBCLCB0eXBlbmFtZS4uLiBUPgpzdHJ1Y3QgaXNfc2FtZV9uPEEsIEIsIFQuLi4+IDoKICAgICAgICBzdGQ6OmNvbmRpdGlvbmFsPHN0ZDo6aXNfc2FtZTxBLCBCPnt9LCBpc19zYW1lX248QiwgVC4uLj4sIHN0ZDo6ZmFsc2VfdHlwZT46OnR5cGUKe307Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBBLCB0eXBlbmFtZSBCPgpzdHJ1Y3QgaXNfc2FtZV9uPEEsIEI+IDoKICAgICAgICBzdGQ6OmlzX3NhbWU8QSwgQj4Ke307Cgp0ZW1wbGF0ZTx0eXBlbmFtZS4uLj4Kc3RydWN0IFBhY2s7CgppbnQgbWFpbigpCnsKCiAgICB0eXBlZGVmIFBhY2s8aW50LCBmbG9hdCwgZG91YmxlLCB2b2lkPiBBOwogICAgdHlwZWRlZiBQYWNrPHZvaWQsIGZsb2F0LCBkb3VibGUsIHZvaWQ+IEI7CiAgICB0eXBlZGVmIFBhY2s8ZmxvYXQsIGJvb2wsIGRvdWJsZSwgdm9pZD4gQzsKICAgIHR5cGVkZWYgUGFjazxmbG9hdCwgaW50LCBjaGFyLCB2b2lkPiBEOwogICAgdHlwZWRlZiBQYWNrPGJvb2wsIGNoYXIsIHZvaWQsIGRvdWJsZT4gRTsKCiAgICBhc3NlcnQoKGFueV9uIDxpc19zYW1lX24sIEEsIEI+KCkpKTsgICAgICAgICAgICAvLyB0cnVlCiAgICBhc3NlcnQoKGFueV9uIDxpc19zYW1lX24sIEEsIEIsIEM+KCkpKTsgICAgICAgICAvLyB0cnVlCiAgICBhc3NlcnQoKGFueV9uIDxpc19zYW1lX24sIEEsIEIsIEMsIEQ+KCkpKTsgICAgICAvLyB0cnVlCiAgICBhc3NlcnQoIShhbnlfbiA8aXNfc2FtZV9uLCBBLCBCLCBDLCBELCBFPigpKSk7ICAvLyBmYWxzZQoKICAgIHN0ZDo6Y291dCA8PCAiUEFTU0VEISIgPDwgc3RkOjplbmRsOwoKICAgIHJldHVybiAwOwp9Cg==