I am running into a problem regarding the appropriate usage of enable_if and template specialization.
After modifying the example (for confidentiality reasons), here's a comparable example:
I have function called "less" that checks if 1st arg is less than 2nd arg. Let's say I want to have 2 different kinds of implementations depending on the type of input - 1 implementation for integer and another for double.
The code that I have so far looks like this -
#include <type_traits> #include <iostream> template <class T, class = typename std::enable_if<std::is_floating_point<T>::value>::type> bool less(T a, T b) { // .... } template <class T, class = typename std::enable_if<std::is_integral<T>::value>::type> bool less(T a, T b) { // .... } int main() { float a; float b; less(a,b); return 0; }
The above code does not compile because - It says that I am re-defining the less method.
Errors are:
Z.cpp:15:19: error: template parameter redefines default argument class = typename std::enable_if<std::is_integral<T>::value>::type> ^ Z.cpp:9:19: note: previous default template argument defined here class = typename std::enable_if<std::is_floating_point<T>::value>::type> ^ Z.cpp:16:11: error: redefinition of 'less' bool less(T a, T b) { ^ Z.cpp:10:11: note: previous definition is here bool less(T a, T b) { ^ Z.cpp:23:5: error: no matching function for call to 'less' less(a,b); ^~~~ Z.cpp:15:43: note: candidate template ignored: disabled by 'enable_if' [with T = float] class = typename std::enable_if<std::is_integral<T>::value>::type> ^ 3 errors generated.
Can someone point out what's the mistake here?
Default template arguments are not part of the signature of a function template. So in your example you have two identical overloads of less
, which is illegal. clang complains about the redefinition of the default argument (which is also illegal according to §14.1/12 [temp.param]), while gcc produces the following error message:
error: redefinition of '
template<class T, class> bool less(T, T)
'
To fix the error move the enable_if
expression from default argument to a dummy template parameter
template <class T, typename std::enable_if<std::is_floating_point<T>::value, int>::type* = nullptr> bool less(T a, T b) { // .... } template <class T, typename std::enable_if<std::is_integral<T>::value, int>::type* = nullptr> bool less(T a, T b) { // .... }
Another option is to use enable_if
in the return type, though I feel this is harder to read.
template <class T> typename std::enable_if<std::is_floating_point<T>::value, bool>::type less(T a, T b) { // .... } template <class T> typename std::enable_if<std::is_integral<T>::value, bool>::type less(T a, T b) { // .... }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With