#include <iostream>
#include <typeinfo>
using namespace std;
template <typename T>
class base {
public:
base (T val = T())
: m_val(val)
{}
base (const base &other)
: base(other.m_val)
{}
virtual void base_specific_method()
{
cout << __func__ << " method called: " << m_val << endl;
}
void each_class_has_this() {
cout << __func__ << " this is boring..." << endl;
}
T m_val;
};
class other {
public:
void each_class_has_this() {
cout << __func__ <<" this is boring..." << endl;
}
};
class derived_i : public base <int>
{
public:
derived_i () : base <int> (10)
{}
virtual void base_specific_method()
{
cout << __func__ <<" Hey! I'm interesting derived! And 10 == " << m_val << endl;
}
};
template <typename T>
class has_specific
{
typedef char one;
typedef long two;
template <typename C> static one test( typeof(&C::base_specific_method) ) ;
template <typename C> static two test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
};
template <typename T>
class caller {
public:
caller (T val = T())
: m_val(val)
{}
void call() {
p_call(m_val);
}
private:
template <typename T1=T>
typename enable_if<!has_specific<T1>::value,void>::type
p_call (T1 &val)
{
val.each_class_has_this();
}
template <typename T1=T>
typename enable_if<has_specific<T1>::value,void>::type
p_call (T1 &val)
{
val.base_specific_method();
}
private:
T m_val;
};
int main ()
{
caller<other> c1;
caller<base<double> > c2;
caller<derived_i > c3;
c1.call();
c2.call();
c3.call();
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZWluZm8+Cgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CmNsYXNzIGJhc2UgewpwdWJsaWM6CiAgICBiYXNlIChUIHZhbCA9IFQoKSkKICAgICAgICA6IG1fdmFsKHZhbCkKICAgIHt9CiAgICBiYXNlIChjb25zdCBiYXNlICZvdGhlcikKICAgICAgICA6IGJhc2Uob3RoZXIubV92YWwpCiAgICB7fQogICAgdmlydHVhbCB2b2lkIGJhc2Vfc3BlY2lmaWNfbWV0aG9kKCkKICAgIHsKICAgICAgICBjb3V0IDw8IF9fZnVuY19fIDw8ICIgbWV0aG9kIGNhbGxlZDogIiA8PCBtX3ZhbCA8PCBlbmRsOwogICAgfQogICAgdm9pZCBlYWNoX2NsYXNzX2hhc190aGlzKCkgewogICAgICAgIGNvdXQgPDwgX19mdW5jX18gPDwgIiB0aGlzIGlzIGJvcmluZy4uLiIgPDwgZW5kbDsKICAgIH0KICAgIFQgbV92YWw7Cn07CmNsYXNzIG90aGVyIHsKcHVibGljOgogICAgdm9pZCBlYWNoX2NsYXNzX2hhc190aGlzKCkgewogICAgICAgIGNvdXQgPDwgX19mdW5jX18gPDwiIHRoaXMgaXMgYm9yaW5nLi4uIiA8PCBlbmRsOwogICAgfQp9OwpjbGFzcyBkZXJpdmVkX2kgOiBwdWJsaWMgYmFzZSA8aW50Pgp7CnB1YmxpYzoKICAgIGRlcml2ZWRfaSAoKSA6IGJhc2UgPGludD4gKDEwKQogICAge30KICAgIHZpcnR1YWwgdm9pZCBiYXNlX3NwZWNpZmljX21ldGhvZCgpCiAgICB7CiAgICAgICAgY291dCA8PCBfX2Z1bmNfXyA8PCIgSGV5ISBJJ20gaW50ZXJlc3RpbmcgZGVyaXZlZCEgQW5kIDEwID09ICIgPDwgbV92YWwgPDwgZW5kbDsKICAgIH0KfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBUPgpjbGFzcyBoYXNfc3BlY2lmaWMKewogICAgdHlwZWRlZiBjaGFyIG9uZTsKICAgIHR5cGVkZWYgbG9uZyB0d287CgogICAgdGVtcGxhdGUgPHR5cGVuYW1lIEM+IHN0YXRpYyBvbmUgdGVzdCggdHlwZW9mKCZDOjpiYXNlX3NwZWNpZmljX21ldGhvZCkgKSA7CiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgQz4gc3RhdGljIHR3byB0ZXN0KC4uLik7ICAgIAoKcHVibGljOgogICAgZW51bSB7IHZhbHVlID0gc2l6ZW9mKHRlc3Q8VD4oMCkpID09IHNpemVvZihjaGFyKSB9Owp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CmNsYXNzIGNhbGxlciB7CnB1YmxpYzoKICAgIGNhbGxlciAoVCB2YWwgPSBUKCkpCiAgICAgICAgOiBtX3ZhbCh2YWwpCiAgICB7fQogICAgdm9pZCBjYWxsKCkgewogICAgICAgIHBfY2FsbChtX3ZhbCk7CiAgICB9CnByaXZhdGU6CiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVDE9VD4KICAgIHR5cGVuYW1lIGVuYWJsZV9pZjwhaGFzX3NwZWNpZmljPFQxPjo6dmFsdWUsdm9pZD46OnR5cGUKICAgIHBfY2FsbCAoVDEgJnZhbCkKICAgIHsKICAgICAgICB2YWwuZWFjaF9jbGFzc19oYXNfdGhpcygpOwogICAgfQogICAgdGVtcGxhdGUgPHR5cGVuYW1lIFQxPVQ+CiAgICB0eXBlbmFtZSBlbmFibGVfaWY8aGFzX3NwZWNpZmljPFQxPjo6dmFsdWUsdm9pZD46OnR5cGUKICAgIHBfY2FsbCAoVDEgJnZhbCkKICAgIHsKICAgICAgICB2YWwuYmFzZV9zcGVjaWZpY19tZXRob2QoKTsKICAgIH0KcHJpdmF0ZToKICAgIFQgbV92YWw7Cn07CgppbnQgbWFpbiAoKQp7CiAgICBjYWxsZXI8b3RoZXI+IGMxOwogICAgY2FsbGVyPGJhc2U8ZG91YmxlPiA+IGMyOwogICAgY2FsbGVyPGRlcml2ZWRfaSA+IGMzOwoKICAgIGMxLmNhbGwoKTsKICAgIGMyLmNhbGwoKTsKICAgIGMzLmNhbGwoKTsKfQ==