#include <iostream>
struct hoge_tag {};
struct foo_tag {};
struct hoge { typedef hoge_tag call_tag; };
struct foo { typedef foo_tag call_tag; };
template<class T> struct call_traits {
typedef T call_tag;
};
template<> struct call_traits<hoge> {
typedef hoge::call_tag call_tag;
};
template<> struct call_traits<foo> {
typedef foo::call_tag call_tag;
};
namespace detail {
void call_(hoge_tag) { std::cout << "hoge." << std::endl; };
void call_(foo_tag) { std::cout << "foo." << std::endl; };
template<class T>
void call_(T) { std::cout << "other." << std::endl; };
};
template<class T>
void call(T) {
typedef typename call_traits<T>::call_tag call_tag;
detail::call_(call_tag());
}
int main() {
call(hoge()); // "hoge."
call(foo()); // "foo."
call(int()); // "other."
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKc3RydWN0IGhvZ2VfdGFnIHt9OwpzdHJ1Y3QgZm9vX3RhZyB7fTsKCnN0cnVjdCBob2dlIHsgdHlwZWRlZiBob2dlX3RhZyBjYWxsX3RhZzsgfTsKc3RydWN0IGZvbyB7IHR5cGVkZWYgZm9vX3RhZyBjYWxsX3RhZzsgfTsKCnRlbXBsYXRlPGNsYXNzIFQ+IHN0cnVjdCBjYWxsX3RyYWl0cyB7CiAgICB0eXBlZGVmIFQgY2FsbF90YWc7Cn07CnRlbXBsYXRlPD4gc3RydWN0IGNhbGxfdHJhaXRzPGhvZ2U+IHsKICAgIHR5cGVkZWYgaG9nZTo6Y2FsbF90YWcgY2FsbF90YWc7Cn07CnRlbXBsYXRlPD4gc3RydWN0IGNhbGxfdHJhaXRzPGZvbz4gewogICAgdHlwZWRlZiBmb286OmNhbGxfdGFnIGNhbGxfdGFnOwp9OwoKbmFtZXNwYWNlIGRldGFpbCB7CiAgICB2b2lkIGNhbGxfKGhvZ2VfdGFnKSB7IHN0ZDo6Y291dCA8PCAiaG9nZS4iIDw8IHN0ZDo6ZW5kbDsgfTsKICAgIHZvaWQgY2FsbF8oZm9vX3RhZykgeyBzdGQ6OmNvdXQgPDwgImZvby4iIDw8IHN0ZDo6ZW5kbDsgfTsKICAgIHRlbXBsYXRlPGNsYXNzIFQ+CiAgICB2b2lkIGNhbGxfKFQpIHsgc3RkOjpjb3V0IDw8ICJvdGhlci4iIDw8IHN0ZDo6ZW5kbDsgfTsKfTsKCnRlbXBsYXRlPGNsYXNzIFQ+CnZvaWQgY2FsbChUKSB7CiAgICB0eXBlZGVmIHR5cGVuYW1lIGNhbGxfdHJhaXRzPFQ+OjpjYWxsX3RhZyBjYWxsX3RhZzsKICAgIGRldGFpbDo6Y2FsbF8oY2FsbF90YWcoKSk7Cn0KCmludCBtYWluKCkgewogICAgY2FsbChob2dlKCkpOyAvLyAiaG9nZS4iCiAgICBjYWxsKGZvbygpKTsgIC8vICJmb28uIgogICAgY2FsbChpbnQoKSk7ICAvLyAib3RoZXIuIgp9Cg==