Tengo funciones para convertir diferentes tipos aritméticos en un tipo de punto flotante de precisión medio (solo un uint16_t
en el nivel más bajo) y tengo diferentes funciones para tipos de fuente de coma flotante y entera, usando SFINAE y std::enable_if
:Diferenciación SFINAE entre firmado y no firmado
template<typename T>
uint16_t to_half(typename std::enable_if<
std::is_floating_point<T>::value,T>::type value)
{
//float to half conversion
}
template<typename T>
uint16_t to_half(typename std::enable_if<
std::is_integral<T>::value,T>::type value)
{
//int to half conversion
}
Estos se llaman internamente a partir de un constructor universal con plantilla de instancias explícita:
template<typename T>
half::half(T rhs)
: data_(detail::conversion::to_half<T>(rhs))
{
}
Esto compila y funciona muy bien. Ahora trato de diferenciar entre números enteros con y sin signo, mediante la sustitución de la segunda función con las dos funciones:
template<typename T>
uint16_t to_half(typename std::enable_if<std::is_integral<T>::value &&
std::is_signed<T>::value,T>::type value)
{
//signed to half conversion
}
template<typename T>
uint16_t to_half(typename std::enable_if<std::is_integral<T>::value &&
std::is_unsigned<T>::value,T>::type value)
{
//unsigned to half conversion
}
Pero una vez que trato de compilar este VS2010 me da
C2995 de error:
"uint16_t math::detail::conversion::to_half(std::enable_if<std::tr1::is_integral<_Ty>::value && std::tr1::is_signed<_Ty>::value, T>::type)"
: Función plantilla ya definida.
Parece que no puede eliminar la ambigüedad entre las dos plantillas, pero obviamente no tuvo problemas con la versión integral junto con la versión de coma flotante.
Pero como no soy tan mago como plantilla, me puede estar faltando algo obvio aquí (o tal vez debería funcionar y es solo un error VS2010). Entonces, ¿por qué no funciona esto y cómo se puede hacer funcionar con la menor sobrecarga de programación posible y en los límites de las características de solo estándar (si es posible)?
No está claro si 'is_signed' /' is_unsigned' es mutuamente exclusivo (hello 'char'?). Intenta hacer que la segunda versión diga '! Std :: is_signed :: value' en su lugar. –
¿Puedes tratar de usar 'std :: is_signed :: value' para uno de los miembros y'! Std :: is_signed :: value' para el otro? Esto es solo para asegurarse de que no solo haya algún tipo que tenga configuraciones incoherentes para 'is_signed' y' is_unsigned'. –
@KerrekSB & Dietmar Hah, ¡eso fue todo! No puedo creer que fue así de fácil. Si alguien lo agrega como respuesta lo aceptaré. –