#include <type_traits>
#include <string>
std::string fooImpl(int i) { return "int!"; }
template <typename T>
void fooImpl(T);
template <typename T>
using HasFooImpl = typename std::is_same<std::string, decltype(fooImpl(std::declval<T>()))>;
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)
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8c3RyaW5nPgogCiAKc3RkOjpzdHJpbmcgZm9vSW1wbChpbnQgaSkgeyByZXR1cm4gImludCEiOyB9CiAKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnZvaWQgZm9vSW1wbChUKTsKIAp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KdXNpbmcgSGFzRm9vSW1wbCA9IHR5cGVuYW1lIHN0ZDo6aXNfc2FtZTxzdGQ6OnN0cmluZywgZGVjbHR5cGUoZm9vSW1wbChzdGQ6OmRlY2x2YWw8VD4oKSkpPjsKIAp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8SGFzRm9vSW1wbDxUPjo6dmFsdWUsIHN0ZDo6c3RyaW5nPjo6dHlwZSAKZm9vKFQmJiB0KQp7CiAgcmV0dXJuIGZvb0ltcGwoc3RkOjpmb3J3YXJkPFQ+KHQpKTsKfQogCnRlbXBsYXRlIDx0eXBlbmFtZSBUPgp0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjwhSGFzRm9vSW1wbDxUPjo6dmFsdWUsIHN0ZDo6c3RyaW5nPjo6dHlwZQpmb28oVCYmIHQpCnsKICAgIHJldHVybiAiZ2VuZXJpYyEiOwp9CiAKc3RydWN0IFh7fTsKIAp0ZW1wbGF0ZSA8Y2xhc3MgVD4Kc3RydWN0IFN7fTsKdGVtcGxhdGUgPGNsYXNzIFQ+CnN0ZDo6c3RyaW5nIGZvb0ltcGwoUzxUPiBjb25zdCYpIHsgcmV0dXJuICJTPFQ+IjsgfQogCiNpbmNsdWRlIDxpb3N0cmVhbT4KaW50IG1haW4oKQp7CiAgc3RkOjpjb3V0IDw8IGZvbygxKSA8PCAnXG4nOwogIHN0ZDo6Y291dCA8PCBmb28oIm5vcGUiKSA8PCAnXG4nOwogIHN0ZDo6Y291dCA8PCBmb28oUzx1bnNpZ25lZD57fSkgPDwgJ1xuJzsKICBzdGQ6OmNvdXQgPDwgZm9vKFh7fSkgPDwgJ1xuJzsKICBzdGQ6OmNvdXQgPDwgZm9vKDMuNCkgPDwgJ1xuJzsgIC8vd2lsbCBjYWxsIGZvb0ltcGwoaW50KQp9