I have functions for converting different arithmetic types to a half precision floating point type (just a uint16_t
on the lowest level) and I have different functions for integer and floating point source types, using SFINAE and std::enable_if
:
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
}
These are called internally from a universal templated constructor by explicit instantiation:
template<typename T>
half::half(T rhs)
: data_(detail::conversion::to_half<T>(rhs))
{
}
This compiles and also works just fine. Now I try to differentiate between signed and unsigned integers, by replacing the second function with the two functions:
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
}
But once I try to compile this VS2010 gives me
error C2995:
"uint16_t math::detail::conversion::to_half( std::enable_if<std::tr1::is_integral<_Ty>::value && std::tr1::is_signed<_Ty>::value, T>::type )"
: function template already defined.
So it seems it cannot disambiguate between the two templates, but it obviously had no problems with the integral version alongside the floating point version.
But since I'm not that much a a template magician I may just be missing something obvious here (or maybe it should actually work and is just a VS2010 bug). So why doesn't this work and how can it be made work with as few programming overhead as possible and in the limits of standard-only features (if even possible)?