c – SFINAE区分签名和未签名

前端之家收集整理的这篇文章主要介绍了c – SFINAE区分签名和未签名前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有将不同算术类型转换为半精度浮点类型的函数(只是最低级别的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给了我

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.

所以它似乎无法消除两个模板之间的歧义,但它显然与浮点版本的积分版本没有问题.

但是因为我不是一个模板魔术师,所以我可能只是在这里遗漏了一些明显的东西(或者它可能真的有用,而且只是一个VS2010的bug).那么为什么这不起作用?如何使用尽可能少的编程开销和仅限标准功能(如果可能的话)?

解决方法

如果这不起作用,则编译器出错.

Two expressions involving template parameters are considered equivalent if two function definitions containing the expressions would satisfy the one definition rule …

这是这里要考虑的最重要的规则(省略了“……”的细节).您的两个模板不满足ODR,因为它们的令牌序列不同.

Two function templates are equivalent if they are declared in the same scope,have the same name,have identical template parameter lists,and have return types and parameter lists that are equivalent using the rules described above to compare expressions involving template parameters.

因此,您的两个模板定义了不同的模板,不会发生冲突.您现在可以检查您的模板是否“功能相同”.如果对于任何可能的模板参数集,则enable_if表达式将始终产生相同的值.但是因为is_unsigned和is_signed不是这样,所以情况也不是这样.如果它会,那么你的代码将是格式错误,但不需要诊断(这实际上意味着“未定义的行为”).

猜你在找的C&C++相关文章