// IsPermutation<Pack1, Pack2>::value has value true if the types in Pack1 are a permutation of the types in Pack2.
#include <iostream>
#include <type_traits>
template <typename, typename> struct ExistsInPack;
template <typename T, template <typename...> class P>
struct ExistsInPack<T, P<>> : std::false_type {};
template <typename T, template <typename...> class P, typename... Rest>
struct ExistsInPack<T, P<T, Rest...>> : std::true_type {};
template <typename T, template <typename...> class P, typename First, typename... Rest>
struct ExistsInPack<T, P<First, Rest...>> : ExistsInPack<T, P<Rest...>> {};
template <std::size_t N, typename T, typename Pack> struct CountHelper;
template <std::size_t N, typename T, template <typename...> class P>
struct CountHelper<N, T, P<>> : std::integral_constant<std::size_t, N> {};
template <std::size_t N, typename T, template <typename...> class P, typename... Rest>
struct CountHelper<N, T, P<T, Rest...>> : CountHelper<N+1, T, P<Rest...>> {};
template <std::size_t N, typename T, template <typename...> class P, typename First, typename... Rest>
struct CountHelper<N, T, P<First, Rest...>> : CountHelper<N, T, P<Rest...>> {};
template <typename T, typename Pack>
using Count = CountHelper<0, T, Pack>; // Count<T, Pack>::value is the number of occurrences of T in Pack.
template <typename Pack1, typename Pack2, typename AlreadyCounted> struct CountFirstType;
template <template <typename...> class P, typename Pack, typename AlreadyCounted>
struct CountFirstType<P<>, Pack, AlreadyCounted> : std::true_type {};
template <template <typename...> class P, typename First, typename... Rest, typename Pack, typename... AlreadyCounted>
struct CountFirstType<P<First, Rest...>, Pack, P<AlreadyCounted...>> : std::conditional_t<
ExistsInPack<First, P<AlreadyCounted...>>::value,
CountFirstType<P<Rest...>, Pack, P<AlreadyCounted...>>,
std::conditional_t<
Count<First, P<First, Rest...>>::value == Count<First, Pack>::value,
CountFirstType<P<Rest...>, Pack, P<AlreadyCounted..., First>>,
std::false_type
>
> {};
template <typename Pack1, typename Pack2> struct IsPermutation;
template <template <typename...> class P, typename... Ts, typename... Us>
struct IsPermutation<P<Ts...>, P<Us...>> : CountFirstType<P<Ts...>, P<Us...>, P<>> {};
template <template <typename...> class P, typename First, typename... Rest1, typename... Rest2>
struct IsPermutation<P<First, Rest1...>, P<First, Rest2...>> : IsPermutation<P<Rest1...>, P<Rest2...>> {};
template <template <typename...> class P>
struct IsPermutation<P<>, P<>> : std::true_type {};
template <template <typename...> class P, typename... Ts>
struct IsPermutation<P<>, P<Ts...>> : std::false_type {};
template <template <typename...> class P, typename... Ts>
struct IsPermutation<P<Ts...>, P<>> : std::false_type {};
// Testing
template <typename...> struct P;
int main() {
std::cout << std::boolalpha << IsPermutation< P<int, char, bool>, P<int, char, bool> >::value << '\n'; // true
std::cout << IsPermutation< P<int, char, bool>, P<int, char, bool, int> >::value << '\n'; // false
std::cout << IsPermutation< P<int, char, bool, int>, P<int, char, bool> >::value << '\n'; // false
std::cout << IsPermutation< P<int, char, bool, long>, P<int, char, long, bool> >::value << '\n'; // true
std::cout << IsPermutation< P<int, char, bool, long, long, bool, long>, P<int, char, long, bool, long, long, bool> >::value << '\n'; // true
std::cout << IsPermutation< P<int, char, bool, long>, P<int, char, long, bool, long> >::value << '\n'; // false
}
Ly8gSXNQZXJtdXRhdGlvbjxQYWNrMSwgUGFjazI+Ojp2YWx1ZSBoYXMgdmFsdWUgdHJ1ZSBpZiB0aGUgdHlwZXMgaW4gUGFjazEgYXJlIGEgcGVybXV0YXRpb24gb2YgdGhlIHR5cGVzIGluIFBhY2syLgoKI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUsIHR5cGVuYW1lPiBzdHJ1Y3QgRXhpc3RzSW5QYWNrOwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHRlbXBsYXRlIDx0eXBlbmFtZS4uLj4gY2xhc3MgUD4Kc3RydWN0IEV4aXN0c0luUGFjazxULCBQPD4+IDogc3RkOjpmYWxzZV90eXBlIHt9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHRlbXBsYXRlIDx0eXBlbmFtZS4uLj4gY2xhc3MgUCwgdHlwZW5hbWUuLi4gUmVzdD4Kc3RydWN0IEV4aXN0c0luUGFjazxULCBQPFQsIFJlc3QuLi4+PiA6IHN0ZDo6dHJ1ZV90eXBlIHt9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHRlbXBsYXRlIDx0eXBlbmFtZS4uLj4gY2xhc3MgUCwgdHlwZW5hbWUgRmlyc3QsIHR5cGVuYW1lLi4uIFJlc3Q+CnN0cnVjdCBFeGlzdHNJblBhY2s8VCwgUDxGaXJzdCwgUmVzdC4uLj4+IDogRXhpc3RzSW5QYWNrPFQsIFA8UmVzdC4uLj4+IHt9OwoKdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IE4sIHR5cGVuYW1lIFQsIHR5cGVuYW1lIFBhY2s+IHN0cnVjdCBDb3VudEhlbHBlcjsKCnRlbXBsYXRlIDxzdGQ6OnNpemVfdCBOLCB0eXBlbmFtZSBULCB0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4+IGNsYXNzIFA+CnN0cnVjdCBDb3VudEhlbHBlcjxOLCBULCBQPD4+IDogc3RkOjppbnRlZ3JhbF9jb25zdGFudDxzdGQ6OnNpemVfdCwgTj4ge307Cgp0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgTiwgdHlwZW5hbWUgVCwgdGVtcGxhdGUgPHR5cGVuYW1lLi4uPiBjbGFzcyBQLCB0eXBlbmFtZS4uLiBSZXN0PgpzdHJ1Y3QgQ291bnRIZWxwZXI8TiwgVCwgUDxULCBSZXN0Li4uPj4gOiBDb3VudEhlbHBlcjxOKzEsIFQsIFA8UmVzdC4uLj4+IHt9OwoKdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IE4sIHR5cGVuYW1lIFQsIHRlbXBsYXRlIDx0eXBlbmFtZS4uLj4gY2xhc3MgUCwgdHlwZW5hbWUgRmlyc3QsIHR5cGVuYW1lLi4uIFJlc3Q+CnN0cnVjdCBDb3VudEhlbHBlcjxOLCBULCBQPEZpcnN0LCBSZXN0Li4uPj4gOiBDb3VudEhlbHBlcjxOLCBULCBQPFJlc3QuLi4+PiB7fTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBQYWNrPgp1c2luZyBDb3VudCA9IENvdW50SGVscGVyPDAsIFQsIFBhY2s+OyAgLy8gQ291bnQ8VCwgUGFjaz46OnZhbHVlIGlzIHRoZSBudW1iZXIgb2Ygb2NjdXJyZW5jZXMgb2YgVCBpbiBQYWNrLgoKdGVtcGxhdGUgPHR5cGVuYW1lIFBhY2sxLCB0eXBlbmFtZSBQYWNrMiwgdHlwZW5hbWUgQWxyZWFkeUNvdW50ZWQ+IHN0cnVjdCBDb3VudEZpcnN0VHlwZTsKCnRlbXBsYXRlIDx0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4+IGNsYXNzIFAsIHR5cGVuYW1lIFBhY2ssIHR5cGVuYW1lIEFscmVhZHlDb3VudGVkPgpzdHJ1Y3QgQ291bnRGaXJzdFR5cGU8UDw+LCBQYWNrLCBBbHJlYWR5Q291bnRlZD4gOiBzdGQ6OnRydWVfdHlwZSB7fTsKCnRlbXBsYXRlIDx0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4+IGNsYXNzIFAsIHR5cGVuYW1lIEZpcnN0LCB0eXBlbmFtZS4uLiBSZXN0LCB0eXBlbmFtZSBQYWNrLCB0eXBlbmFtZS4uLiBBbHJlYWR5Q291bnRlZD4Kc3RydWN0IENvdW50Rmlyc3RUeXBlPFA8Rmlyc3QsIFJlc3QuLi4+LCBQYWNrLCBQPEFscmVhZHlDb3VudGVkLi4uPj4gOiBzdGQ6OmNvbmRpdGlvbmFsX3Q8CglFeGlzdHNJblBhY2s8Rmlyc3QsIFA8QWxyZWFkeUNvdW50ZWQuLi4+Pjo6dmFsdWUsCglDb3VudEZpcnN0VHlwZTxQPFJlc3QuLi4+LCBQYWNrLCBQPEFscmVhZHlDb3VudGVkLi4uPj4sCglzdGQ6OmNvbmRpdGlvbmFsX3Q8CgkJQ291bnQ8Rmlyc3QsIFA8Rmlyc3QsIFJlc3QuLi4+Pjo6dmFsdWUgPT0gQ291bnQ8Rmlyc3QsIFBhY2s+Ojp2YWx1ZSwKCQlDb3VudEZpcnN0VHlwZTxQPFJlc3QuLi4+LCBQYWNrLCBQPEFscmVhZHlDb3VudGVkLi4uLCBGaXJzdD4+LAoJCXN0ZDo6ZmFsc2VfdHlwZQoJPgo+IHt9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFBhY2sxLCB0eXBlbmFtZSBQYWNrMj4gc3RydWN0IElzUGVybXV0YXRpb247Cgp0ZW1wbGF0ZSA8dGVtcGxhdGUgPHR5cGVuYW1lLi4uPiBjbGFzcyBQLCB0eXBlbmFtZS4uLiBUcywgdHlwZW5hbWUuLi4gVXM+CnN0cnVjdCBJc1Blcm11dGF0aW9uPFA8VHMuLi4+LCBQPFVzLi4uPj4gOiBDb3VudEZpcnN0VHlwZTxQPFRzLi4uPiwgUDxVcy4uLj4sIFA8Pj4ge307Cgp0ZW1wbGF0ZSA8dGVtcGxhdGUgPHR5cGVuYW1lLi4uPiBjbGFzcyBQLCB0eXBlbmFtZSBGaXJzdCwgdHlwZW5hbWUuLi4gUmVzdDEsIHR5cGVuYW1lLi4uIFJlc3QyPgpzdHJ1Y3QgSXNQZXJtdXRhdGlvbjxQPEZpcnN0LCBSZXN0MS4uLj4sIFA8Rmlyc3QsIFJlc3QyLi4uPj4gOiBJc1Blcm11dGF0aW9uPFA8UmVzdDEuLi4+LCBQPFJlc3QyLi4uPj4ge307Cgp0ZW1wbGF0ZSA8dGVtcGxhdGUgPHR5cGVuYW1lLi4uPiBjbGFzcyBQPgpzdHJ1Y3QgSXNQZXJtdXRhdGlvbjxQPD4sIFA8Pj4gOiBzdGQ6OnRydWVfdHlwZSB7fTsKCnRlbXBsYXRlIDx0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4+IGNsYXNzIFAsIHR5cGVuYW1lLi4uIFRzPgpzdHJ1Y3QgSXNQZXJtdXRhdGlvbjxQPD4sIFA8VHMuLi4+PiA6IHN0ZDo6ZmFsc2VfdHlwZSB7fTsKCnRlbXBsYXRlIDx0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4+IGNsYXNzIFAsIHR5cGVuYW1lLi4uIFRzPgpzdHJ1Y3QgSXNQZXJtdXRhdGlvbjxQPFRzLi4uPiwgUDw+PiA6IHN0ZDo6ZmFsc2VfdHlwZSB7fTsKCi8vIFRlc3RpbmcKdGVtcGxhdGUgPHR5cGVuYW1lLi4uPiBzdHJ1Y3QgUDsKCmludCBtYWluKCkgewoJc3RkOjpjb3V0IDw8IHN0ZDo6Ym9vbGFscGhhIDw8IElzUGVybXV0YXRpb248IFA8aW50LCBjaGFyLCBib29sPiwgUDxpbnQsIGNoYXIsIGJvb2w+ID46OnZhbHVlIDw8ICdcbic7ICAvLyB0cnVlCglzdGQ6OmNvdXQgPDwgSXNQZXJtdXRhdGlvbjwgUDxpbnQsIGNoYXIsIGJvb2w+LCBQPGludCwgY2hhciwgYm9vbCwgaW50PiA+Ojp2YWx1ZSA8PCAnXG4nOyAgLy8gZmFsc2UKCXN0ZDo6Y291dCA8PCBJc1Blcm11dGF0aW9uPCBQPGludCwgY2hhciwgYm9vbCwgaW50PiwgUDxpbnQsIGNoYXIsIGJvb2w+ID46OnZhbHVlIDw8ICdcbic7ICAvLyBmYWxzZQoJc3RkOjpjb3V0IDw8IElzUGVybXV0YXRpb248IFA8aW50LCBjaGFyLCBib29sLCBsb25nPiwgUDxpbnQsIGNoYXIsIGxvbmcsIGJvb2w+ID46OnZhbHVlIDw8ICdcbic7ICAvLyB0cnVlCglzdGQ6OmNvdXQgPDwgSXNQZXJtdXRhdGlvbjwgUDxpbnQsIGNoYXIsIGJvb2wsIGxvbmcsIGxvbmcsIGJvb2wsIGxvbmc+LCBQPGludCwgY2hhciwgbG9uZywgYm9vbCwgbG9uZywgbG9uZywgYm9vbD4gPjo6dmFsdWUgPDwgJ1xuJzsgIC8vIHRydWUKCXN0ZDo6Y291dCA8PCBJc1Blcm11dGF0aW9uPCBQPGludCwgY2hhciwgYm9vbCwgbG9uZz4sIFA8aW50LCBjaGFyLCBsb25nLCBib29sLCBsb25nPiA+Ojp2YWx1ZSA8PCAnXG4nOyAgLy8gZmFsc2UKfQo=