#include <iostream>
class A
{
public:
void foo()
{
std::cout << __func__ << " calling\n";
}
void special_bar_A()
{
std::cout << __func__ << " calling\n";
}
void baz()
{
std::cout << __func__ << " calling\n";
}
};
class B
{
public:
void foo()
{
std::cout << __func__ << " calling\n";
}
void special_bar_B()
{
std::cout << __func__ << " calling\n";
}
void baz()
{
std::cout << __func__ << " calling\n";
}
};
template<class T> void special_stuff(T &)
{
std::cout << "something went wrong\n";
}
template<>
void special_stuff(A &a)
{
a.special_bar_A();
}
template<>
void special_stuff(B &b)
{
b.special_bar_B();
}
template<class T>
void do_stuff()
{
T t;
t.foo();
special_stuff<T>(t);
t.baz();
}
int main()
{
do_stuff<A>();
do_stuff<B>();
}
CiNpbmNsdWRlIDxpb3N0cmVhbT4KCmNsYXNzIEEKewogICBwdWJsaWM6CiAgIHZvaWQgZm9vKCkKICAgewogICAgICBzdGQ6OmNvdXQgPDwgX19mdW5jX18gPDwgIiBjYWxsaW5nXG4iOwogICB9CiAgIHZvaWQgc3BlY2lhbF9iYXJfQSgpCiAgIHsKICAgICAgc3RkOjpjb3V0IDw8IF9fZnVuY19fIDw8ICIgY2FsbGluZ1xuIjsKICAgfQogICB2b2lkIGJheigpCiAgIHsKICAgICAgc3RkOjpjb3V0IDw8IF9fZnVuY19fIDw8ICIgY2FsbGluZ1xuIjsKICAgfQp9OwoKY2xhc3MgQgp7CiAgIHB1YmxpYzoKICAgdm9pZCBmb28oKQogICB7CiAgICAgIHN0ZDo6Y291dCA8PCBfX2Z1bmNfXyA8PCAiIGNhbGxpbmdcbiI7CiAgIH0KICAgdm9pZCBzcGVjaWFsX2Jhcl9CKCkKICAgewogICAgICBzdGQ6OmNvdXQgPDwgX19mdW5jX18gPDwgIiBjYWxsaW5nXG4iOwogICB9CiAgIHZvaWQgYmF6KCkKICAgewogICAgICBzdGQ6OmNvdXQgPDwgX19mdW5jX18gPDwgIiBjYWxsaW5nXG4iOwogICB9Cn07Cgp0ZW1wbGF0ZTxjbGFzcyBUPiB2b2lkIHNwZWNpYWxfc3R1ZmYoVCAmKQp7CiAgIHN0ZDo6Y291dCA8PCAic29tZXRoaW5nIHdlbnQgd3JvbmdcbiI7Cn0KCnRlbXBsYXRlPD4Kdm9pZCBzcGVjaWFsX3N0dWZmKEEgJmEpCnsKICAgYS5zcGVjaWFsX2Jhcl9BKCk7Cn0KCnRlbXBsYXRlPD4Kdm9pZCBzcGVjaWFsX3N0dWZmKEIgJmIpCnsKICAgYi5zcGVjaWFsX2Jhcl9CKCk7Cn0KCnRlbXBsYXRlPGNsYXNzIFQ+CnZvaWQgZG9fc3R1ZmYoKQp7CiAgIFQgdDsKICAgdC5mb28oKTsKICAgc3BlY2lhbF9zdHVmZjxUPih0KTsKICAgdC5iYXooKTsKfQoKaW50IG1haW4oKQp7CiAgIGRvX3N0dWZmPEE+KCk7CiAgIGRvX3N0dWZmPEI+KCk7Cn0K