#include <iostream>
#include <utility>
#include <tuple>
namespace details
{
template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
for_each(const std::tuple<Tp...> &, FuncT) // Unused arguments are given no names.
{ }
template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
for_each(const std::tuple<Tp...>& t, FuncT f)
{
f(std::get<I>(t));
for_each<I + 1, FuncT, Tp...>(t, f);
}
template <typename T>
struct traverseType
{
void operator () (const T& t)
{
std::cout << "it is a generic T:" << t << std::endl;
}
};
template <>
struct traverseType<int>
{
void operator () (int i)
{
std::cout << "it is a int:" << i << std::endl;
}
};
struct traverseTypeCaller
{
template <typename T>
void operator () (const T& t)
{
details::traverseType<T>()(t);
}
};
template <typename ...T>
struct traverseType<std::tuple<T...>>
{
void operator () (const std::tuple<T...>& t)
{
std::cout << "it is a tuple:" << std::endl;
for_each(t, traverseTypeCaller());
}
};
}
template <typename T>
void traverseType(const T& t)
{
details::traverseTypeCaller()(t);
}
int main()
{
const auto t = std::make_tuple(42, '*', std::make_tuple(4, 2));
traverseType(t);
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dXRpbGl0eT4KI2luY2x1ZGUgPHR1cGxlPgoKbmFtZXNwYWNlIGRldGFpbHMKewoKdGVtcGxhdGU8c3RkOjpzaXplX3QgSSA9IDAsIHR5cGVuYW1lIEZ1bmNULCB0eXBlbmFtZS4uLiBUcD4KaW5saW5lIHR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPEkgPT0gc2l6ZW9mLi4uKFRwKSwgdm9pZD46OnR5cGUKICBmb3JfZWFjaChjb25zdCBzdGQ6OnR1cGxlPFRwLi4uPiAmLCBGdW5jVCkgLy8gVW51c2VkIGFyZ3VtZW50cyBhcmUgZ2l2ZW4gbm8gbmFtZXMuCiAgeyB9Cgp0ZW1wbGF0ZTxzdGQ6OnNpemVfdCBJID0gMCwgdHlwZW5hbWUgRnVuY1QsIHR5cGVuYW1lLi4uIFRwPgppbmxpbmUgdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8SSA8IHNpemVvZi4uLihUcCksIHZvaWQ+Ojp0eXBlCiAgZm9yX2VhY2goY29uc3Qgc3RkOjp0dXBsZTxUcC4uLj4mIHQsIEZ1bmNUIGYpCiAgewogICAgZihzdGQ6OmdldDxJPih0KSk7CiAgICBmb3JfZWFjaDxJICsgMSwgRnVuY1QsIFRwLi4uPih0LCBmKTsKICB9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IHRyYXZlcnNlVHlwZQp7Cgl2b2lkIG9wZXJhdG9yICgpIChjb25zdCBUJiB0KQoJewoJCXN0ZDo6Y291dCA8PCAiaXQgaXMgYSBnZW5lcmljIFQ6IiA8PCB0IDw8IHN0ZDo6ZW5kbDsKCX0KfTsKCnRlbXBsYXRlIDw+CnN0cnVjdCB0cmF2ZXJzZVR5cGU8aW50Pgp7Cgl2b2lkIG9wZXJhdG9yICgpIChpbnQgaSkKCXsKCQlzdGQ6OmNvdXQgPDwgIml0IGlzIGEgaW50OiIgPDwgaSA8PCBzdGQ6OmVuZGw7Cgl9Cn07CgpzdHJ1Y3QgdHJhdmVyc2VUeXBlQ2FsbGVyCnsKCXRlbXBsYXRlIDx0eXBlbmFtZSBUPgoJdm9pZCBvcGVyYXRvciAoKSAoY29uc3QgVCYgdCkKCXsKCQlkZXRhaWxzOjp0cmF2ZXJzZVR5cGU8VD4oKSh0KTsKCX0KfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSAuLi5UPgpzdHJ1Y3QgdHJhdmVyc2VUeXBlPHN0ZDo6dHVwbGU8VC4uLj4+CnsKCXZvaWQgb3BlcmF0b3IgKCkgKGNvbnN0IHN0ZDo6dHVwbGU8VC4uLj4mIHQpCgl7CgkJc3RkOjpjb3V0IDw8ICJpdCBpcyBhIHR1cGxlOiIgPDwgc3RkOjplbmRsOwoJCWZvcl9lYWNoKHQsIHRyYXZlcnNlVHlwZUNhbGxlcigpKTsKCX0KfTsKCn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBUPgp2b2lkIHRyYXZlcnNlVHlwZShjb25zdCBUJiB0KQp7CglkZXRhaWxzOjp0cmF2ZXJzZVR5cGVDYWxsZXIoKSh0KTsKfQoKaW50IG1haW4oKQp7Cgljb25zdCBhdXRvIHQgPSBzdGQ6Om1ha2VfdHVwbGUoNDIsICcqJywgc3RkOjptYWtlX3R1cGxlKDQsIDIpKTsKCgl0cmF2ZXJzZVR5cGUodCk7CgoJcmV0dXJuIDA7Cn0K