#include <type_traits>
#include <iostream>
template<class T>
class has_addition
{
template <typename C> static std::true_type test( decltype(
std::declval<C>() + std::declval<C>()
)* );
template <typename> static std::false_type test(...);
public:
enum { value = decltype(test<T>(0))::value };
};
template<class T>
class X
{
public:
template <typename T1 = T>
typename std::enable_if<!has_addition<T1>::value, void>::type use(T1 t)
{
std::cout << "without addition" << std::endl;
T1 tt = t;
}
template <typename T1 = T>
typename std::enable_if<has_addition<T1>::value, void>::type use(T1 t)
{
std::cout << "with addition" << std::endl;
auto tt = t + t;
}
};
int main()
{
X<int> x1; x1.use(1);
X<void*> x2; x2.use(nullptr);
return 0;
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8aW9zdHJlYW0+Cgp0ZW1wbGF0ZTxjbGFzcyBUPgpjbGFzcyBoYXNfYWRkaXRpb24KewogICAgdGVtcGxhdGUgPHR5cGVuYW1lIEM+IHN0YXRpYyBzdGQ6OnRydWVfdHlwZSB0ZXN0KCBkZWNsdHlwZSgKICAgIAkgICAgc3RkOjpkZWNsdmFsPEM+KCkgKyBzdGQ6OmRlY2x2YWw8Qz4oKQogICAgCSkqICk7CiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWU+IHN0YXRpYyBzdGQ6OmZhbHNlX3R5cGUgdGVzdCguLi4pOwogICAgCnB1YmxpYzoKICAgIGVudW0geyB2YWx1ZSA9IGRlY2x0eXBlKHRlc3Q8VD4oMCkpOjp2YWx1ZSB9Owp9OwoKdGVtcGxhdGU8Y2xhc3MgVD4KY2xhc3MgWAp7CnB1YmxpYzoKCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVDEgPSBUPgoJdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8IWhhc19hZGRpdGlvbjxUMT46OnZhbHVlLCB2b2lkPjo6dHlwZSB1c2UoVDEgdCkKCXsKCQlzdGQ6OmNvdXQgPDwgIndpdGhvdXQgYWRkaXRpb24iIDw8IHN0ZDo6ZW5kbDsKCQlUMSB0dCA9IHQ7Cgl9CgogICAgdGVtcGxhdGUgPHR5cGVuYW1lIFQxID0gVD4KCXR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPGhhc19hZGRpdGlvbjxUMT46OnZhbHVlLCB2b2lkPjo6dHlwZSB1c2UoVDEgdCkKCXsKCQlzdGQ6OmNvdXQgPDwgIndpdGggYWRkaXRpb24iIDw8IHN0ZDo6ZW5kbDsKCQlhdXRvIHR0ID0gdCArIHQ7Cgl9Cgp9OwoKaW50IG1haW4oKQp7CglYPGludD4geDE7IHgxLnVzZSgxKTsKCVg8dm9pZCo+IHgyOyB4Mi51c2UobnVsbHB0cik7CiAgICByZXR1cm4gMDsKfQ==