c++ - std:: enable_if: parámetro vs parámetro de plantilla
alias c++ (3)
El problema es que el compilador ve 2 sobrecargas del mismo método, que contienen los mismos argumentos (ninguno, en este caso) y el mismo valor de retorno. Usted no puede proporcionar tal definición. La forma más sencilla de hacer esto es usar SFINAE en el valor de retorno de la función:
template <class T>
class check
{
public:
template< class U = T>
static typename std::enable_if<std::is_same<U, int>::value, U>::type readVal()
{
return BuffCheck.getInt();
}
template< class U = T>
static typename std::enable_if<std::is_same<U, double>::value, U>::type readVal()
{
return BuffCheck.getDouble();
}
};
De esa manera, estás proporcionando 2 sobrecargas diferentes. Uno devuelve un int, el otro devuelve un doble y solo se puede crear una instancia con un cierto T.
Estoy creando un verificador de entrada que necesita tener funciones específicas para entero y / o doble (por ejemplo, ''isPrime'' solo debería estar disponible para enteros).
Si estoy usando enable_if
como parámetro está funcionando perfectamente:
template <class T>
class check
{
public:
template< class U = T>
inline static U readVal(typename std::enable_if<std::is_same<U, int>::value >::type* = 0)
{
return BuffCheck.getInt();
}
template< class U = T>
inline static U readVal(typename std::enable_if<std::is_same<U, double>::value >::type* = 0)
{
return BuffCheck.getDouble();
}
};
pero si lo estoy usando como un parámetro de plantilla (como se muestra en http://en.cppreference.com/w/cpp/types/enable_if )
template <class T>
class check
{
public:
template< class U = T, class = typename std::enable_if<std::is_same<U, int>::value>::type >
inline static U readVal()
{
return BuffCheck.getInt();
}
template< class U = T, class = typename std::enable_if<std::is_same<U, double>::value>::type >
inline static U readVal()
{
return BuffCheck.getDouble();
}
};
entonces tengo el siguiente error:
error: ‘template<class T> template<class U, class> static U check::readVal()’ cannot be overloaded
error: with ‘template<class T> template<class U, class> static U check::readVal()’
No puedo entender lo que está mal en la segunda versión.
Los argumentos de la plantilla predeterminada no forman parte de la firma de una plantilla (por lo que ambas definiciones intentan definir la misma plantilla dos veces). Sin embargo, sus tipos de parámetros son parte de la firma. Para que puedas hacer
template <class T>
class check
{
public:
template< class U = T,
typename std::enable_if<std::is_same<U, int>::value, int>::type = 0>
inline static U readVal()
{
return BuffCheck.getInt();
}
template< class U = T,
typename std::enable_if<std::is_same<U, double>::value, int>::type = 0>
inline static U readVal()
{
return BuffCheck.getDouble();
}
};
Sé que esta pregunta es sobre std::enable_if
, sin embargo, me gusta brindar una solución alternativa para resolver el mismo problema sin enable_if. Requiere C ++ 17
template <class T>
class check
{
public:
inline static T readVal()
{
if constexpr (std::is_same_v<T, int>)
return BuffCheck.getInt();
else if constexpr (std::is_same_v<T, double>)
return BuffCheck.getDouble();
}
};
Este código parece más como si lo escribiera en tiempo de ejecución. Todas las ramas deben ser sintácticas correctas, sin embargo, la semántica no tiene que serlo. En este caso, si T es int, el getDouble no está causando errores de compilación (o advertencias) ya que el compilador no lo controla ni lo utiliza.
Si el tipo de retorno de la función sería complejo de mencionar, siempre puede usar auto
como tipo de retorno.