首页 > 解决方案 > C ++如何禁用具有不同符号变量比较的特定行的编译器警告?

问题描述

我的 C++ 项目中有一个烦人的编译器警告。它在一个模板函数中,它检查它的参数是否适合特定类型的范围,这被称为模板参数(在标准库中找不到它,它有吗?)。

我知道有符号到无符号整数类型的比较很棘手,因此我专门为不同的有符号整数使用了这个函数,在有符号整数与无符号比较之前,我首先检查有符号整数是否为非负数。但是 gcc 会针对这种安全情况发出警告。我不想用 -Wsign-compare 完全禁用这个警告,因为它很有用。代码如下:

template <typename TRange, typename TSuspect, typename TCommonSignedness>
bool isInRangeOfHelper(const TSuspect & suspect,
                       const TCommonSignedness &,
                       const TCommonSignedness &)
{
    return std::numeric_limits<TRange>::min() <= suspect
         && suspect <= std::numeric_limits<TRange>::max();
}

template <typename TRange, typename TSuspect>
bool isInRangeOfHelper(const TSuspect & suspect, 
                       const std::true_type &, 
                       const std::false_type &)
{
    return suspect <= std::numeric_limits<TRange>::max();
}

template <typename TRange, typename TSuspect>
bool isInRangeOfHelper(const TSuspect & suspect, 
                        const std::false_type &, 
                        const std::true_type &)
{
    return 0 <= suspect 
           && suspect <= std::numeric_limits<TRange>::max();  // WARNING HERE
}


template <typename TRange, typename TSuspect>
bool isInRangeOf(const TSuspect & suspect){
    return isInRangeOfHelper<TRange>(suspect,
                           std::is_signed<TRange>(),
                           std::is_signed<TSuspect>());
}

template <typename TRange>
bool isInRangeOf(const TRange & suspect){ return true; }



int main(int argc, char *argv[]){

    if (!isInRangeOf<unsigned int>(-1)){
        std::cout << "false";
    } else {
        std::cout << "predicate error";
        std::terminate();
    }
    return 0;
}
// warning: comparison of integer expressions of different signedness: 
// ‘const int’ and ‘unsigned int’ [-Wsign-compare]
// return 0 <= suspect && suspect <= std::numeric_limits<TRange>::max();
//                        ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

标签: c++

解决方案


一旦你验证suspect了它是非负的,你就可以安全地将它转换为它的类型的无符号版本:

template <typename TRange, typename TSuspect>
bool isInRangeOfHelper(const TSuspect & suspect, 
                        const std::false_type &, 
                        const std::true_type &)
{
    return 0 <= suspect 
           && static_cast<std::make_unsigned_t<TSuspect>>(suspect) <= std::numeric_limits<TRange>::max();
}

[现场示例]


推荐阅读