#include <type_traits>
#include <string>
std::string fooImpl(int i) { return "int!"; }
template <class T>
struct HasFooImpl_ {
template <typename C>
static std::true_type test(decltype(fooImpl(std::declval<C>()))*);
template <typename C>
static std::false_type test(...);
typedef decltype(test<T>(0)) type;
};
template <typename T>
using HasFooImpl = typename HasFooImpl_<T>::type;
template <typename T>
typename std::enable_if<HasFooImpl<T>::value, std::string>::type
foo(T&& t)
{
return fooImpl(std::forward<T>(t));
}
template <typename T>
typename std::enable_if<!HasFooImpl<T>::value, std::string>::type
foo(T&& t)
{
return "generic!";
}
struct X{};
template <class T>
struct S{};
template <class T>
std::string fooImpl(S<T> const&) { return "S<T>"; }
#include <iostream>
int main()
{
std::cout << foo(1) << '\n';
std::cout << foo("nope") << '\n';
std::cout << foo(S<unsigned>{}) << '\n';
std::cout << foo(X{}) << '\n';
std::cout << foo(3.4) << '\n'; //will call fooImpl(int)
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8c3RyaW5nPgogCiAKc3RkOjpzdHJpbmcgZm9vSW1wbChpbnQgaSkgeyByZXR1cm4gImludCEiOyB9CiAKdGVtcGxhdGUgPGNsYXNzIFQ+CnN0cnVjdCBIYXNGb29JbXBsXyB7CiAgdGVtcGxhdGUgPHR5cGVuYW1lIEM+CiAgc3RhdGljIHN0ZDo6dHJ1ZV90eXBlIHRlc3QoZGVjbHR5cGUoZm9vSW1wbChzdGQ6OmRlY2x2YWw8Qz4oKSkpKik7CiAgdGVtcGxhdGUgPHR5cGVuYW1lIEM+IAogIHN0YXRpYyBzdGQ6OmZhbHNlX3R5cGUgdGVzdCguLi4pOwogIHR5cGVkZWYgZGVjbHR5cGUodGVzdDxUPigwKSkgdHlwZTsKfTsKIAp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KdXNpbmcgSGFzRm9vSW1wbCA9IHR5cGVuYW1lIEhhc0Zvb0ltcGxfPFQ+Ojp0eXBlOwogCnRlbXBsYXRlIDx0eXBlbmFtZSBUPgp0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxIYXNGb29JbXBsPFQ+Ojp2YWx1ZSwgc3RkOjpzdHJpbmc+Ojp0eXBlIApmb28oVCYmIHQpCnsKICByZXR1cm4gZm9vSW1wbChzdGQ6OmZvcndhcmQ8VD4odCkpOwp9CiAKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPCFIYXNGb29JbXBsPFQ+Ojp2YWx1ZSwgc3RkOjpzdHJpbmc+Ojp0eXBlCmZvbyhUJiYgdCkKewogICAgcmV0dXJuICJnZW5lcmljISI7Cn0KIApzdHJ1Y3QgWHt9OwogCnRlbXBsYXRlIDxjbGFzcyBUPgpzdHJ1Y3QgU3t9Owp0ZW1wbGF0ZSA8Y2xhc3MgVD4Kc3RkOjpzdHJpbmcgZm9vSW1wbChTPFQ+IGNvbnN0JikgeyByZXR1cm4gIlM8VD4iOyB9CiAKIAojaW5jbHVkZSA8aW9zdHJlYW0+CmludCBtYWluKCkKewogIHN0ZDo6Y291dCA8PCBmb28oMSkgPDwgJ1xuJzsKICBzdGQ6OmNvdXQgPDwgZm9vKCJub3BlIikgPDwgJ1xuJzsKICBzdGQ6OmNvdXQgPDwgZm9vKFM8dW5zaWduZWQ+e30pIDw8ICdcbic7CiAgc3RkOjpjb3V0IDw8IGZvbyhYe30pIDw8ICdcbic7CiAgc3RkOjpjb3V0IDw8IGZvbygzLjQpIDw8ICdcbic7ICAvL3dpbGwgY2FsbCBmb29JbXBsKGludCkKfQ==