#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==