C++如何使用不同的签名变量比较禁用特定行的编译器警告?

Vee*_*aha 3 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();
//                        ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

Rei*_*ica 5

一旦您验证了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();
}
Run Code Online (Sandbox Code Playgroud)

[实例]


o11*_*11c 5

之前的代码:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
Run Code Online (Sandbox Code Playgroud)

代码后:

#pragma GCC diagnostic pop
Run Code Online (Sandbox Code Playgroud)

如果要从宏扩展此_Pragma()格式以支持非GCC编译器,请使用等效形式

边缘情况:

  • 在旧版本的GCC中(4.6吗?文档未说),这必须围绕该函数进行,但是现在可以在任何范围内完成。

  • 如果您尝试在宏中禁止显示警告,然后在同一宏中触发它,则可能会出现问题。

  • note:对于某些诊断,某些编译器版本可能无法抑制关联的。