#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)
}