3

What is the difference of these two implementations and which of them should I use, since whey both work the same if I call them from main:

template<class T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
void test( const T& t ){
    printf("int\n");
}

template<class T, typename std::enable_if<std::is_floating_point<T>::value, int>::type = 0>
void test( const T& t ){
        printf("float\n");
}

vs

template<class T>
typename std::enable_if<std::is_integral<T>::value>::type test1( const T& t ){
    printf("int\n");
}

template<class T>
typename std::enable_if<std::is_floating_point<T>::value>::type test1( const T& t ){
    printf("float\n");
}

and the main:

int main(){ 
   test(1);
   test(1.0); 

   test1(1);
   test1(1.0); 
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
Martin Perry
  • 9,232
  • 8
  • 46
  • 114

1 Answers1

3

The default second argument of std::enable_if is void, so that the expression typename std::enable_if<std::is_integral<T>::value>::type = 0 is ill formed.


The case with enable_if for the return value does not introduce an unnecessary template argument with an initializer and therefore is more elegant and less error-prone for function templates.

As you have noticed, it is easier to make a mistake when introducing that unnecessary template argument.

Class templates, on the other hand, must use the extra template argument for SFINAE, since there is no return value.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • I am sorry, I had an typo in that – Martin Perry Mar 28 '18 at 09:39
  • I'd prefer an answer saying both are legal and behave similarly (this answers the question), the choice between the two being a simple preference, yours being the later because reasons (that let you give your opinion). – YSC Mar 28 '18 at 09:46
  • For the first sample, If i change signature to: `typename std::enable_if::value>::type* = nullptr`, I can use `void` in second `enable_if` argument – Martin Perry Mar 28 '18 at 09:46