#include <iostream>
#include <typeinfo>
template
<
template <typename...> class BeCurry,
typename... Params
>
struct Curry
{
using type = BeCurry<Params...>;
};
template
<
template <typename...> class BeCurry
>
struct Curry<BeCurry>
{
using type = BeCurry<>;
};
template
<
template <typename...> class BeCurry,
typename... Params
>
struct Currying
{
template <typename... OtherParams>
using curried = typename Curry<BeCurry, Params..., OtherParams...>::type;
template <typename... OtherParams>
using type = typename curried<OtherParams...>::type;
template <typename... NewParams>
using apply = Currying<curried, NewParams...>;
};
template<typename T>
struct Test1
{
using type = int;
};
template<typename T, typename T1>
struct Test2
{
using type = char*;
};
template <typename T>
void print_type(T t)
{
std::cout << typeid(t).name() << std::endl;
}
int main()
{
print_type(Currying<Test1>::type<int>{});
print_type(Currying<Test1>::apply<int>::type<>{});
print_type(Currying<Test2>::type<int, char>{});
print_type(Currying<Test2>::apply<int>::type<char>{});
print_type(Currying<Test2>::apply<int>::apply<char>::type<>{});
print_type(Currying<Test2>::apply<int, char>::type<>{});
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZWluZm8+Cgp0ZW1wbGF0ZQoJPAoJCXRlbXBsYXRlIDx0eXBlbmFtZS4uLj4gY2xhc3MgQmVDdXJyeSwKCQl0eXBlbmFtZS4uLiBQYXJhbXMKCT4Kc3RydWN0IEN1cnJ5CnsKCXVzaW5nIHR5cGUgPSBCZUN1cnJ5PFBhcmFtcy4uLj47Cn07Cgp0ZW1wbGF0ZQoJPAoJCXRlbXBsYXRlIDx0eXBlbmFtZS4uLj4gY2xhc3MgQmVDdXJyeQoJPgpzdHJ1Y3QgQ3Vycnk8QmVDdXJyeT4KewoJdXNpbmcgdHlwZSA9IEJlQ3Vycnk8PjsKfTsKCnRlbXBsYXRlCgk8CgkJdGVtcGxhdGUgPHR5cGVuYW1lLi4uPiBjbGFzcyBCZUN1cnJ5LAoJCXR5cGVuYW1lLi4uIFBhcmFtcwoJPgpzdHJ1Y3QgQ3VycnlpbmcKewoJdGVtcGxhdGUgPHR5cGVuYW1lLi4uIE90aGVyUGFyYW1zPgoJdXNpbmcgY3VycmllZCA9IHR5cGVuYW1lIEN1cnJ5PEJlQ3VycnksIFBhcmFtcy4uLiwgT3RoZXJQYXJhbXMuLi4+Ojp0eXBlOwoKCXRlbXBsYXRlIDx0eXBlbmFtZS4uLiBPdGhlclBhcmFtcz4KCXVzaW5nIHR5cGUgPSB0eXBlbmFtZSBjdXJyaWVkPE90aGVyUGFyYW1zLi4uPjo6dHlwZTsKCQoJdGVtcGxhdGUgPHR5cGVuYW1lLi4uIE5ld1BhcmFtcz4KCXVzaW5nIGFwcGx5ID0gQ3Vycnlpbmc8Y3VycmllZCwgTmV3UGFyYW1zLi4uPjsKfTsKCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnN0cnVjdCBUZXN0MQp7Cgl1c2luZyB0eXBlID0gaW50Owp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgVCwgdHlwZW5hbWUgVDE+CnN0cnVjdCBUZXN0Mgp7Cgl1c2luZyB0eXBlID0gY2hhcio7Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kdm9pZCBwcmludF90eXBlKFQgdCkKewoJc3RkOjpjb3V0IDw8IHR5cGVpZCh0KS5uYW1lKCkgPDwgc3RkOjplbmRsOwp9CgppbnQgbWFpbigpCnsKCXByaW50X3R5cGUoQ3Vycnlpbmc8VGVzdDE+Ojp0eXBlPGludD57fSk7CglwcmludF90eXBlKEN1cnJ5aW5nPFRlc3QxPjo6YXBwbHk8aW50Pjo6dHlwZTw+e30pOwoJcHJpbnRfdHlwZShDdXJyeWluZzxUZXN0Mj46OnR5cGU8aW50LCBjaGFyPnt9KTsKCXByaW50X3R5cGUoQ3Vycnlpbmc8VGVzdDI+OjphcHBseTxpbnQ+Ojp0eXBlPGNoYXI+e30pOwoJcHJpbnRfdHlwZShDdXJyeWluZzxUZXN0Mj46OmFwcGx5PGludD46OmFwcGx5PGNoYXI+Ojp0eXBlPD57fSk7CglwcmludF90eXBlKEN1cnJ5aW5nPFRlc3QyPjo6YXBwbHk8aW50LCBjaGFyPjo6dHlwZTw+e30pOwoJcmV0dXJuIDA7Cn0=