我有以下模板:
一个用于未签名,另一个用于签名.有没有什么优雅的方式摆脱编译器警告而不压制它?
warning: comparison between signed and unsigned integer expressions
我需要为每种类型写功能,例如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 std::enable_if<std::is_signed<X>::value,aUpperLimit ); throw(std::out_of_range("Invalid Range")); } }
解决方法
让我解释一下你在这里遇到的错误.
对于我来说,您通常希望对所有三个参数使用相同的类型.最直接的解决方案是这个定义:
template<typename X> void debugValidateParameter( X aValuetocheck,X aLowerLimit,X aUpperLimit) { if( (aValuetocheck > aUpperLimit) || (aValuetocheck < aLowerLimit) ) { log("ERROR: ValidateParameters,aUpperLimit ); throw(std::out_of_range("Invalid Range")); } }
但是,如果然后使用无符号变量和两个文字整数来调用该函数,例如:
debugValidateParameter(someUnsignedInteger,100);
您将收到一个错误,因为该类型不能推导出来 – 因此,所有类型为X的参数都需要传递一个完全相同类型的值.
所以推断X型是不明确的,因此是不可能的.对我来说,它看起来像是要根据传递的第一个参数(“实际值”)推导出类型,并且只是尝试将边界转换为同一类型.换句话说,一些不强迫你写的东西
debugValidateParameter(someUnsignedInteger,0u,100u);
这可以通过禁用第二和第三参数的类型扣除来实现,通过将它们的类型指定为identity_t< X>而不是只有X,其中identity_t被定义为
template<typename T> struct identity { typedef T type; }; template<typename T> using identity_t = typename identity<T>::type;
所以你的功能定义就变成了
template<typename X> void debugValidateParameter( X aValuetocheck,identity_t<X> aLowerLimit,identity_t<X> aUpperLimit) { if( (aValuetocheck > aUpperLimit) || (aValuetocheck < aLowerLimit) ) { log("ERROR: ValidateParameters,aUpperLimit ); throw(std::out_of_range("Invalid Range")); } }