#include <iostream>
#include <type_traits>
template<template<typename...> class C, typename... T>
struct is_valid_specialization {
typedef struct { char _; } yes;
typedef struct { yes _[2]; } no;
template<template<typename...> class D>
static yes test(D<T...>*);
template<template<typename...> class D>
static no test(...);
constexpr static bool value = (sizeof(test<C>(0)) == sizeof(yes));
};
namespace detail {
template<template<typename...> class BeCurry, bool = false, typename... S>
struct Currying {
template<typename... T>
using apply = Currying<BeCurry, is_valid_specialization<BeCurry, S..., T...>::value, S..., T...>;
};
template<template<typename...> class BeCurry, typename... S>
struct Currying<BeCurry, true, S...> {
template<typename... T>
using apply = Currying<BeCurry, is_valid_specialization<BeCurry, S..., T...>::value, S..., T...>;
using type = typename BeCurry<S...>::type;
};
}
template<template<typename...> class BeCurry>
using Currying = detail::Currying<BeCurry, is_valid_specialization<BeCurry>::value>;
template<typename T>
struct Test1 { using type = int; };
template<typename T1, typename T2>
struct Test2 { using type = char*; };
template<typename...>
struct Test3 { using type = double; };
using curry = Currying<Test1>;
using curry2 = Currying<Test2>;
using curry3 = Currying<Test3>;
template<typename T>
void pretty_print(T) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
int main() {
pretty_print(typename curry::apply<char>::type{});
pretty_print(typename curry2::apply<int>::apply<char>::type{});
pretty_print(typename curry3::type{});
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+Cgp0ZW1wbGF0ZTx0ZW1wbGF0ZTx0eXBlbmFtZS4uLj4gY2xhc3MgQywgdHlwZW5hbWUuLi4gVD4Kc3RydWN0IGlzX3ZhbGlkX3NwZWNpYWxpemF0aW9uIHsKCXR5cGVkZWYgc3RydWN0IHsgY2hhciBfOyB9IHllczsKCXR5cGVkZWYgc3RydWN0IHsgeWVzIF9bMl07IH0gbm87CgoJdGVtcGxhdGU8dGVtcGxhdGU8dHlwZW5hbWUuLi4+IGNsYXNzIEQ+CglzdGF0aWMgeWVzIHRlc3QoRDxULi4uPiopOwoJdGVtcGxhdGU8dGVtcGxhdGU8dHlwZW5hbWUuLi4+IGNsYXNzIEQ+CglzdGF0aWMgbm8gdGVzdCguLi4pOwoKCWNvbnN0ZXhwciBzdGF0aWMgYm9vbCB2YWx1ZSA9IChzaXplb2YodGVzdDxDPigwKSkgPT0gc2l6ZW9mKHllcykpOwp9OwoKbmFtZXNwYWNlIGRldGFpbCB7CgoJdGVtcGxhdGU8dGVtcGxhdGU8dHlwZW5hbWUuLi4+IGNsYXNzIEJlQ3VycnksIGJvb2wgPSBmYWxzZSwgdHlwZW5hbWUuLi4gUz4KCXN0cnVjdCBDdXJyeWluZyB7CgoJCXRlbXBsYXRlPHR5cGVuYW1lLi4uIFQ+CgkJdXNpbmcgYXBwbHkgPSBDdXJyeWluZzxCZUN1cnJ5LCBpc192YWxpZF9zcGVjaWFsaXphdGlvbjxCZUN1cnJ5LCBTLi4uLCBULi4uPjo6dmFsdWUsIFMuLi4sIFQuLi4+OwoJfTsKCgl0ZW1wbGF0ZTx0ZW1wbGF0ZTx0eXBlbmFtZS4uLj4gY2xhc3MgQmVDdXJyeSwgdHlwZW5hbWUuLi4gUz4KCXN0cnVjdCBDdXJyeWluZzxCZUN1cnJ5LCB0cnVlLCBTLi4uPiB7CgoJCXRlbXBsYXRlPHR5cGVuYW1lLi4uIFQ+CgkJdXNpbmcgYXBwbHkgPSBDdXJyeWluZzxCZUN1cnJ5LCBpc192YWxpZF9zcGVjaWFsaXphdGlvbjxCZUN1cnJ5LCBTLi4uLCBULi4uPjo6dmFsdWUsIFMuLi4sIFQuLi4+OwoKCQl1c2luZyB0eXBlID0gdHlwZW5hbWUgQmVDdXJyeTxTLi4uPjo6dHlwZTsKCX07Cn0KCnRlbXBsYXRlPHRlbXBsYXRlPHR5cGVuYW1lLi4uPiBjbGFzcyBCZUN1cnJ5Pgp1c2luZyBDdXJyeWluZyA9IGRldGFpbDo6Q3Vycnlpbmc8QmVDdXJyeSwgaXNfdmFsaWRfc3BlY2lhbGl6YXRpb248QmVDdXJyeT46OnZhbHVlPjsKCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnN0cnVjdCBUZXN0MSB7IHVzaW5nIHR5cGUgPSBpbnQ7IH07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUMSwgdHlwZW5hbWUgVDI+CnN0cnVjdCBUZXN0MiB7IHVzaW5nIHR5cGUgPSBjaGFyKjsgfTsKCnRlbXBsYXRlPHR5cGVuYW1lLi4uPgpzdHJ1Y3QgVGVzdDMgeyB1c2luZyB0eXBlID0gZG91YmxlOyB9OwoKdXNpbmcgY3VycnkgID0gQ3Vycnlpbmc8VGVzdDE+Owp1c2luZyBjdXJyeTIgPSBDdXJyeWluZzxUZXN0Mj47CnVzaW5nIGN1cnJ5MyA9IEN1cnJ5aW5nPFRlc3QzPjsKCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnZvaWQgcHJldHR5X3ByaW50KFQpIHsKCXN0ZDo6Y291dCA8PCBfX1BSRVRUWV9GVU5DVElPTl9fIDw8IHN0ZDo6ZW5kbDsKfQoKaW50IG1haW4oKSB7CglwcmV0dHlfcHJpbnQodHlwZW5hbWUgY3Vycnk6OmFwcGx5PGNoYXI+Ojp0eXBle30pOwoJcHJldHR5X3ByaW50KHR5cGVuYW1lIGN1cnJ5Mjo6YXBwbHk8aW50Pjo6YXBwbHk8Y2hhcj46OnR5cGV7fSk7CglwcmV0dHlfcHJpbnQodHlwZW5hbWUgY3VycnkzOjp0eXBle30pOwp9