У меня есть функции для преобразования различных арифметических типов в тип с плавающей запятой половинной точности (просто uint16_t
на самом низком уровне), и у меня есть разные функции для целых типов источников и типов с плавающей запятой, используя SFINAE и 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
}
Они вызываются внутри универсального шаблонного конструктора путем явного создания экземпляра:
template<typename T>
half::half(T rhs)
: data_(detail::conversion::to_half<T>(rhs))
{
}
Это компилируется и также отлично работает. Теперь я пытаюсь различать целые числа со знаком и без знака, заменяя вторую функцию двумя функциями:
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
}
Но как только я пытаюсь скомпилировать этот VS2010, я получаю
ошибка 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 )"
: шаблон функции уже определен.
Таким образом, кажется, что он не может устранить неоднозначность между двумя шаблонами, но у него, очевидно, не было проблем с интегральной версией наряду с версией с плавающей запятой.
Но так как я не такой уж волшебник шаблонов, я могу просто упустить здесь что-то очевидное (или, может быть, это действительно должно работать, и это просто ошибка VS2010). Так почему же это не работает и как заставить его работать с минимальными издержками программирования и в пределах стандартных функций (если это вообще возможно)?
is_signed
/is_unsigned
взаимоисключающие (приветchar
?). Попробуйте сделать так, чтобы во второй версии вместо этого было!std::is_signed<T>::value
. - person Kerrek SB   schedule 15.02.2012std::is_signed<T>::value
для одного из участников и!std::is_signed<T>::value
для другого? Это просто для того, чтобы убедиться, что не существует какого-то типа с несовместимыми настройками дляis_signed
иis_unsigned
. - person Dietmar Kühl   schedule 15.02.2012char
не является ни целочисленным типом со знаком, ни целочисленным типом без знака. Но IIRCis_signed
иis_unsigned
позаботятся об этом: только один из них сообщитtrue
заchar
. - person Johannes Schaub - litb   schedule 15.02.2012char
в порядке. Однако перечисления и указатели всегда ложны; Я думаю, потому что они не арифметические типы. - person Kerrek SB   schedule 15.02.2012