摆脱有符号和无符号整数表达式之间比较的优雅方法

use*_*942 9 c++ c++11

我有以下模板:

一个用于无符号,另一个用于签名.是否有任何优雅的方法来摆脱编译器警告而不抑制它?

 warning: comparison between signed and unsigned integer expressions
Run Code Online (Sandbox Code Playgroud)

我是否需要为每种类型编写函数,例如uint8,uint16等.?

template<typename X,typename Y,typename Z, typename std::enable_if<std::is_unsigned<X>::value, bool>::type = true >
void debugValidateParameter( X aValueToCheck, Y aLowerLimit, Z aUpperLimit)
{
   if( (aValueToCheck > aUpperLimit) || (aValueToCheck < aLowerLimit) )
   {
    log("ERROR: ValidateParameters, aValueToCheck = % , aLowerLimit= % , aUpperLimit= %  \n", aValueToCheck, aLowerLimit, aUpperLimit );
    throw(std::out_of_range("Invalid Range"));
   }
}

template<typename X,typename Y,typename Z, typename std::enable_if<std::is_signed<X>::value, bool>::type = true >
void debugValidateParameter( X aValueToCheck, Y aLowerLimit, Z aUpperLimit)
{
   if( (aValueToCheck > aUpperLimit) || (aValueToCheck < aLowerLimit) )
   {
    log("ERROR: ValidateParameters, aValueToCheck = % , aLowerLimit= % , aUpperLimit= %  \n", aValueToCheck, aLowerLimit, aUpperLimit );
    throw(std::out_of_range("Invalid Range"));
   }
}
Run Code Online (Sandbox Code Playgroud)

lee*_*mes 12

让我解释一下你在这里遇到的问题.

对我来说,看起来您通常希望对所有三个参数使用相同的类型.最直接的解决方案是这个定义:

template<typename X>
void debugValidateParameter( X aValueToCheck, X aLowerLimit, X aUpperLimit)
{
   if( (aValueToCheck > aUpperLimit) || (aValueToCheck < aLowerLimit) )
   {
    log("ERROR: ValidateParameters, aValueToCheck = % , aLowerLimit= % , aUpperLimit= %  \n", aValueToCheck, aLowerLimit, aUpperLimit );
    throw(std::out_of_range("Invalid Range"));
   }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您随后使用无符号变量和两个文字整数调用该函数,例如:

debugValidateParameter(someUnsignedInteger, 0, 100);
Run Code Online (Sandbox Code Playgroud)

你会得到一个错误,因为无法推断出类型 - 为此,所有带类型的参数都X需要传递一个完全相同类型的值.因此,推断类型X是模糊的,因此是不可能的.对我来说,看起来你想要根据传递的第一个参数("实际值")推断出类型,并且只是尝试将边界转换为相同的类型.换句话说,一些不会强迫你写的东西

debugValidateParameter(someUnsignedInteger, 0u, 100u);
Run Code Online (Sandbox Code Playgroud)

这可以通过禁用第二个和第三个参数的类型推导来完成,方法是将其类型指定为identity_t<X>而不仅仅是X,其中identity_t定义为

template<typename T>
struct identity { typedef T type; };

template<typename T>
using identity_t = typename identity<T>::type;
Run Code Online (Sandbox Code Playgroud)

那么你的函数定义就变成了

template<typename X>
void debugValidateParameter( X aValueToCheck, identity_t<X> aLowerLimit, identity_t<X> aUpperLimit)
{
   if( (aValueToCheck > aUpperLimit) || (aValueToCheck < aLowerLimit) )
   {
    log("ERROR: ValidateParameters, aValueToCheck = % , aLowerLimit= % , aUpperLimit= %  \n", aValueToCheck, aLowerLimit, aUpperLimit );
    throw(std::out_of_range("Invalid Range"));
   }
}
Run Code Online (Sandbox Code Playgroud)

在这里,您可以看到Live Demo中的代码.