C ++如何禁用具有不同符号变量比较的特定行的编译器警告?
Posted
技术标签:
【中文标题】C ++如何禁用具有不同符号变量比较的特定行的编译器警告?【英文标题】:C++ How to disable compiler warning for particular line with different signedness variables comparison? 【发布时间】:2018-05-24 18:50:56 【问题描述】:我的 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();
// ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
【问题讨论】:
使用演员表和评论。 @n.m.使用答案部分。 【参考方案1】:一旦您验证了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();
[Live example]
【讨论】:
【参考方案2】:代码前:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
代码后:
#pragma GCC diagnostic pop
如果您想从宏扩展它以支持非 GCC 编译器,请使用等效的 _Pragma()
形式
边缘情况:
在旧版本的 GCC(4.6?文档没有说)中,这必须围绕函数,但现在可以在任何范围内完成。
如果您尝试在宏中隐藏警告,然后在同一个宏中触发它,则可能会出现问题。
某些编译器版本可能无法抑制关联的note:
s 以进行某些诊断。
【讨论】:
【参考方案3】:有几个选项:
1 UINT_MAX
isInRangeOf<unsigned int>( std::numeric_limits<unsigned_int>::max() );
isInRangeOf<unsigned int>( UINT_MAX );
// GCC specific
isInRangeOf<unsigned int>( __UINT32_MAX__ );
2 位技巧
isInRangeOf<unsigned int>( static_cast<unsigned int>(-1) )
isInRangeOf<unsigned int>( ~0 )
isInRangeOf<unsigned int>( 0xFFFFFFFF )
3 通过 pragma 指令抑制警告
(在进行一些模板元编程时,此选项对于一些未使用的参数警告很有用)
#ifdef __GNUG__
# define PUSH_IGNORE_WSIGN_CMP\
_Pragma("GCC diagnostic push")\
_Pragma("GCC diagnostic ignored \"-Wsign-compare\" ")
# define POP_IGNORE_WSIGN_CMP _Pragma("GCC diagnostic pop")
#elif defined(_MSC_VER)
# define PUSH_IGNORE_WSIGN_CMP
_Pragma("warning( push )")\
_Pragma("warning( disable : C4018)")
# define POP_IGNORE_WSIGN_CMP _Pragma("warning( pop )")
#endif
PUSH_IGNORE_WSIGN_CMP
if (!isInRangeOf<unsigned int>(-1))
POP_IGNORE_WSIGN_CMP
std::cout << "false";
【讨论】:
以上是关于C ++如何禁用具有不同符号变量比较的特定行的编译器警告?的主要内容,如果未能解决你的问题,请参考以下文章