C++

Templates

Template specialization using SFINAE (based on source, source ):
As a template parameter:

struct Check2
{
   template<typename T, typename std::enable_if<
            std::is_integral<T>::value>::type* = nullptr>
   T read() { return 42; }

   template<typename T, typename std::enable_if<
            std::is_floating_point<T>::value>::type* = nullptr>
   T read() { return 3.14; }   
};

As return type:
struct Check3
{
   template<typename T>
   typename std::enable_if<std::is_integral<T>::value, T>::type
   read() { return 42; }

   template<typename T>
   typename std::enable_if<std::is_floating_point<T>::value, T>::type
   read() { return 3.14; }   
};

As return type via auto:
struct Check4
{
   template<typename T>   
   auto read() -> typename std::enable_if<std::is_integral<T>::value, T>::type
   { return 42; }

   template<typename T>   
   auto read() -> typename std::enable_if<std::is_floating_point<T>::value, T>::type
   { return 3.14; }   
};

And here is main:
int main()
{
  Check2 c2;
  Check3 c3;
  Check4 c4;
  
  std::cout << c2.read<int>() << "\n";
  std::cout << c2.read<double>() << "\n";
  
  std::cout << c3.read<int>() << "\n";
  std::cout << c3.read<double>() << "\n";
  
  std::cout << c4.read<int>() << "\n";
  std::cout << c4.read<double>() << "\n";
}



Some other interesting things:

template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) // return type depends on template parameters
                                      // return type can be deduced since C++14
{
    return t+u;
}

int main()
{
 std::cout << add(1, 2) << "\n";
 std::cout << add(1.1, 2) << "\n";
}

Martin Prantl 2018, Using http://hilite.me/