c++ templates c++11 sfinae enable-if

c++ - Especialización de plantillas y enable_if problemas



templates c++11 (1)

Esta pregunta ya tiene una respuesta aquí:

Me encuentro con un problema relacionado con el uso apropiado de enable_if y la especialización de plantillas.

Después de modificar el ejemplo (por razones de confidencialidad), aquí hay un ejemplo comparable:

Tengo una función llamada "menos" que comprueba si el primer argumento es menor que el segundo argumento. Digamos que quiero tener 2 tipos diferentes de implementaciones dependiendo del tipo de entrada: 1 implementación para entero y otra para doble.

El código que tengo hasta ahora se ve así:

#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; }

El código anterior no se compila porque: dice que estoy redefiniendo el método less.

Los errores son:

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.

¿Alguien puede señalar cuál es el error aquí?


Los argumentos de plantilla predeterminados no son parte de la firma de una plantilla de función. Entonces, en su ejemplo, tiene dos sobrecargas idénticas de less , lo cual es ilegal. clang se queja de la redefinición del argumento predeterminado (que también es ilegal según §14.1 / 12 [temp.param]), mientras que gcc produce el siguiente mensaje de error:

error: redefinición de '' template<class T, class> bool less(T, T) ''

Para corregir el error, mueva la expresión enable_if del argumento predeterminado a un parámetro de plantilla ficticio

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) { // .... }

Otra opción es usar enable_if en el tipo de retorno, aunque creo que es más difícil de leer.

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) { // .... }