c++templatesc++11sfinaeenable-if

Why should I avoid std::enable_if in function signatures


Scott Meyers posted content and status of his next book EC++11. He wrote that one item in the book could be "Avoid std::enable_if in function signatures".

std::enable_if can be used as a function argument, as a return type or as a class template or function template parameter to conditionally remove functions or classes from overload resolution.

In this question all three solution are shown.

As function parameter:

template<typename T>
struct Check1
{
   template<typename U = T>
   U read(typename std::enable_if<
          std::is_same<U, int>::value >::type* = 0) { return 42; }

   template<typename U = T>
   U read(typename std::enable_if<
          std::is_same<U, double>::value >::type* = 0) { return 3.14; }   
};

As template parameter:

template<typename T>
struct Check2
{
   template<typename U = T, typename std::enable_if<
            std::is_same<U, int>::value, int>::type = 0>
   U read() { return 42; }

   template<typename U = T, typename std::enable_if<
            std::is_same<U, double>::value, int>::type = 0>
   U read() { return 3.14; }   
};

As return type:

template<typename T>
struct Check3
{
   template<typename U = T>
   typename std::enable_if<std::is_same<U, int>::value, U>::type read() {
      return 42;
   }

   template<typename U = T>
   typename std::enable_if<std::is_same<U, double>::value, U>::type read() {
      return 3.14;
   }   
};

Solution

  • Put the hack in the template parameters.

    The enable_if on template parameter approach has at least two advantages over the others:

    For me, the readability aspect is the big motivating factor in this choice.