c++ - Especialización de plantillas y enable_if problemas
templates c++11 (1)
Esta pregunta ya tiene una respuesta aquí:
- SFINAE trabajando en el tipo de retorno pero no como respuestas de parámetro 3 de plantilla
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) {
// ....
}