У меня есть функции для преобразования различных арифметических типов в тип с плавающей точкой с половинной точностью (только на uint16_t
на самом низком уровне), и у меня есть разные функции для типов источников с целыми числами и с плавающей точкой, используя SFINAE и std::enable_if
:Дифференциация SFINAE между подписанным и неподписанным
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' является взаимоисключающим (hello 'char'?). Попробуйте сделать вторую версию: '! Std :: is_signed :: value' вместо. –
Можете ли вы попытаться использовать 'std :: is_signed :: value' для одного из членов и'! Std :: is_signed :: value' для другого? Это просто, чтобы убедиться, что существует не только некоторый тип, который имеет непоследовательные параметры для 'is_signed' и' is_unsigned'. –
@ KerrekSB & Dietmar Hah, вот и все! Не могу поверить, что это было так просто. Если кто-то добавит его в качестве ответа, я соглашусь с ним. –