#include <iostream>
#include <type_traits>
#include <typeinfo>
template<typename ...Args>
struct holder;
namespace
{
template<typename ...Args>
struct print_helper;
template<typename Arg, typename ...Args>
struct print_helper<Arg, Args...>
{
static void print()
{
std::cout << typeid(Arg).name() << ", ";
print_helper<Args...>::print();
}
};
template<typename Arg>
struct print_helper<Arg>
{
static void print()
{
std::cout << typeid(Arg).name() << std::endl;
}
};
template<typename ...Args>
struct print_helper<holder<Args...>>
{
static void print()
{
print_helper<Args...>::print();
}
};
}
template<typename ...Args>
void print()
{
print_helper<Args...>::print();
}
namespace
{
template<typename Applier, typename T>
struct apply_helper
{
typedef typename Applier::template apply<T>::type type;
};
template<typename Applier, typename ... Args>
struct transform_helper
{
typedef holder<typename apply_helper<Applier, Args>::type...> type;
};
}
template<typename Applier, typename ... Args>
struct transform
{
typedef typename transform_helper<Applier, Args...>::type type;
};
template<typename Applier, typename ... Args>
struct transform<Applier, holder<Args...>>
{
typedef typename transform<Applier, Args...>::type type;
};
namespace
{
template<typename T>
struct type_replacer_helper
{
typedef T type;
};
template<>
struct type_replacer_helper<int>
{
typedef float type;
};
}
struct type_replacer
{
template<typename T>
struct apply
{
typedef typename type_replacer_helper<T>::type type;
};
};
using namespace std;
int main() {
typedef holder<int, int, char, int, float> t1;
typedef typename transform<type_replacer, t1>::type t2;
print<t1>();
print<t2>();
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CiNpbmNsdWRlIDx0eXBlaW5mbz4KCnRlbXBsYXRlPHR5cGVuYW1lIC4uLkFyZ3M+CnN0cnVjdCBob2xkZXI7CgpuYW1lc3BhY2UKewoJdGVtcGxhdGU8dHlwZW5hbWUgLi4uQXJncz4KCXN0cnVjdCBwcmludF9oZWxwZXI7CgoJdGVtcGxhdGU8dHlwZW5hbWUgQXJnLCB0eXBlbmFtZSAuLi5BcmdzPgoJc3RydWN0IHByaW50X2hlbHBlcjxBcmcsIEFyZ3MuLi4+Cgl7CgkJc3RhdGljIHZvaWQgcHJpbnQoKQoJCXsKCQkJc3RkOjpjb3V0IDw8IHR5cGVpZChBcmcpLm5hbWUoKSA8PCAiLCAiOwoJCQlwcmludF9oZWxwZXI8QXJncy4uLj46OnByaW50KCk7CgkJfQoJfTsKCgl0ZW1wbGF0ZTx0eXBlbmFtZSBBcmc+CglzdHJ1Y3QgcHJpbnRfaGVscGVyPEFyZz4KCXsKCQlzdGF0aWMgdm9pZCBwcmludCgpCgkJewoJCQlzdGQ6OmNvdXQgPDwgdHlwZWlkKEFyZykubmFtZSgpIDw8IHN0ZDo6ZW5kbDsKCQl9Cgl9OwoKCXRlbXBsYXRlPHR5cGVuYW1lIC4uLkFyZ3M+CglzdHJ1Y3QgcHJpbnRfaGVscGVyPGhvbGRlcjxBcmdzLi4uPj4KCXsKCQlzdGF0aWMgdm9pZCBwcmludCgpCgkJewoJCQlwcmludF9oZWxwZXI8QXJncy4uLj46OnByaW50KCk7CgkJfQoJfTsKfQoKdGVtcGxhdGU8dHlwZW5hbWUgLi4uQXJncz4Kdm9pZCBwcmludCgpCnsKCXByaW50X2hlbHBlcjxBcmdzLi4uPjo6cHJpbnQoKTsKfQoKbmFtZXNwYWNlCnsKCXRlbXBsYXRlPHR5cGVuYW1lIEFwcGxpZXIsIHR5cGVuYW1lIFQ+CglzdHJ1Y3QgYXBwbHlfaGVscGVyCgl7CgkJdHlwZWRlZiB0eXBlbmFtZSBBcHBsaWVyOjp0ZW1wbGF0ZSBhcHBseTxUPjo6dHlwZSB0eXBlOwoJfTsKCgl0ZW1wbGF0ZTx0eXBlbmFtZSBBcHBsaWVyLCB0eXBlbmFtZSAuLi4gQXJncz4KCXN0cnVjdCB0cmFuc2Zvcm1faGVscGVyCgl7CgkJdHlwZWRlZiBob2xkZXI8dHlwZW5hbWUgYXBwbHlfaGVscGVyPEFwcGxpZXIsIEFyZ3M+Ojp0eXBlLi4uPiB0eXBlOwoJfTsKfQoKdGVtcGxhdGU8dHlwZW5hbWUgQXBwbGllciwgdHlwZW5hbWUgLi4uIEFyZ3M+CnN0cnVjdCB0cmFuc2Zvcm0KewoJdHlwZWRlZiB0eXBlbmFtZSB0cmFuc2Zvcm1faGVscGVyPEFwcGxpZXIsIEFyZ3MuLi4+Ojp0eXBlIHR5cGU7Cn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBBcHBsaWVyLCB0eXBlbmFtZSAuLi4gQXJncz4Kc3RydWN0IHRyYW5zZm9ybTxBcHBsaWVyLCBob2xkZXI8QXJncy4uLj4+CnsKCXR5cGVkZWYgdHlwZW5hbWUgdHJhbnNmb3JtPEFwcGxpZXIsIEFyZ3MuLi4+Ojp0eXBlIHR5cGU7Cn07CgpuYW1lc3BhY2UKewoJdGVtcGxhdGU8dHlwZW5hbWUgVD4KCXN0cnVjdCB0eXBlX3JlcGxhY2VyX2hlbHBlcgoJewoJCXR5cGVkZWYgVCB0eXBlOwoJfTsKCgl0ZW1wbGF0ZTw+CglzdHJ1Y3QgdHlwZV9yZXBsYWNlcl9oZWxwZXI8aW50PgoJewoJCXR5cGVkZWYgZmxvYXQgdHlwZTsKCX07Cn0KCnN0cnVjdCB0eXBlX3JlcGxhY2VyCnsKCXRlbXBsYXRlPHR5cGVuYW1lIFQ+CglzdHJ1Y3QgYXBwbHkKCXsKCQl0eXBlZGVmIHR5cGVuYW1lIHR5cGVfcmVwbGFjZXJfaGVscGVyPFQ+Ojp0eXBlIHR5cGU7Cgl9Owp9OwoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCmludCBtYWluKCkgewoJCgl0eXBlZGVmIGhvbGRlcjxpbnQsIGludCwgY2hhciwgaW50LCBmbG9hdD4gdDE7Cgl0eXBlZGVmIHR5cGVuYW1lIHRyYW5zZm9ybTx0eXBlX3JlcGxhY2VyLCB0MT46OnR5cGUgdDI7CgkKCXByaW50PHQxPigpOwoJcHJpbnQ8dDI+KCk7CgkKCXJldHVybiAwOwp9