Why does enable_if_t in template arguments complains about redefinitions?

c++, c++14, enable-if, sfinae, templates

Solution

Let's remove some code.

template<
  class T,
  class U/* = std::enable_if_t<std::is_same<int, T>::value>*/
 >
void g() { }

template<
  class T,
  class U/* = std::enable_if_t<std::is_same<double, T>::value>*/
 >
void g() { }

would you be surprised if the compiler rejected the two above templates?

They are both template functions of "type" `template<class,class>void()`. The fact that the 2nd type argument has a different default value matters not. That would be like expecting two different `print(string, int)` functions with different default `int` values to overload. ;)

In the first case we have:

template<
  typename T,
  typename std::enable_if<std::is_same<int, T>::value>::type* = nullptr
>
void f() { }

template<
  typename T,
  typename std::enable_if<std::is_same<double, T>::value>::type* = nullptr
>
void f() { }

here we cannot remove the `enable_if` clause. Updating to `enable_if_t`:

template<
  class T,
  std::enable_if_t<std::is_same<int, T>::value, int>* = nullptr
>
void f() { }

template<
  class T,
  std::enable_if_t<std::is_same<double, T>::value, int>* = nullptr
>
void f() { }

I also replaced a use of `typename` with `class`. I suspect your confusion was because `typename` has two meanings -- one as a marker for a kind of `template` argument, and another as a disambiguator for a dependent type.

Here the 2nd argument is a pointer, whose type is dependent on the first. The compiler cannot determine if these two conflict without first substituting in the type `T` -- and you'll note that they will never actually conflict.

Problem

I have the following case that works using `std::enable_if` : ``` template<typename T, typename std::enable_if<std::is_same<int, T>::value>::type* = nullptr> void f() { } template<typename T, typename std::enable_if<std::is_same<double, T>::value>::type* = nullptr> void f() { } ``` Now, I saw in cppreference the new syntax, much cleaner in my opinion : `typename = std::enable_if_t<std::is_same<int, T>::value>>` I wanted to port my code : ``` template<typename T, typename = std::enable_if_t<std::is_same<int, T>::value>> void g() { } template<typename T, typename = std::enable_if_t<std::is_same<double, T>::value>> void g() { } ``` But now GCC (5.2) complains : ``` error: redefinition of 'template<class T, class> void g()' void g() { } ``` Why is that so ? What can I do to have the new, more concise syntax in this case if this is possible ?

Original source

Related problems