我在本地项目中找到了这种形式的代码:
#include <iostream>
const unsigned LOWER_LIMIT = 0;
int main(int argc, char* argv[])
{
if (argc > 1) {
unsigned a = atoi(argv[1]);
if (a < LOWER_LIMIT) {
// if (a - LOWER_LIMIT > a) {
std::cerr << "lower\n";
a = LOWER_LIMIT;
}
}
}
atoi()
部分仅用于演示的可运行性,并且在实际情况下由软件的其他部分提供。自然地,这段代码会产生一个警告,显示最近的g++ -Wall -Wextra
:
comparison of unsigned expression < 0 is always false
维护者不希望更改比较,因为常量LOWER_LIMIT将来可能会更改,并且他希望它可以不更改地继续工作。另外,他还希望该类型也为无符号。我抑制警告的第一个想法是
if (a - LOWER_LIMIT > a) {
使用未签名的下溢。但是对于某些人来说,这种解决方案有些难以理解。我找到了另一种解决方案:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wtype-limits"
if (a < LOWER_LIMIT) {
#pragma GCC diagnostic pop
这可行,但是我从GCC
部分假定这不是便携式解决方案。
是否存在一种可移植,通用且易于理解的方法来避免出现此警告,并且仍使某些开发人员能够简单地更改常量,而不必了解正在进行比较的代码库的这一部分?>
编辑:我对此有一个模板解决方案,但感觉有点过头了:
template<typename NumericTypeA, typename NumericTypeB>
typename std::enable_if<std::is_unsigned<NumericTypeA>::value &&
std::is_unsigned<NumericTypeB>::value, bool >::type
is_smaller_than(NumericTypeA a, NumericTypeB b)
{
return (a - b > a);
}
template<typename NumericTypeA, typename NumericTypeB>
typename std::enable_if<std::is_signed<NumericTypeA>::value &&
std::is_signed<NumericTypeB>::value, bool >::type
is_smaller_than(NumericTypeA a, NumericTypeB b)
{
return (a < b);
}
编辑2:如果编译器检测到比较始终为假,则不必检查以下语句并确定这是可以的(在响应中也建议) ?
if ((LOWER_LIMIT > 0) && (a < LOWER_LIMIT)) {
感觉编译器应该在没有警告的情况下接受它,但是不幸的是,在这种情况下它确实会发出警告。
答案 0 :(得分:2)
有便携式的#pragma吗?
不。 #pragma
是根据定义实现定义的。
特别是警告选项在编译器之间千差万别。
维护者不想要...
由于涉及到维护人员,因此我认为所讨论的代码在第三方提供的包含的标头中。
您可以将编译器配置为不报告来自第三方标头的警告。对于GCC,可以使用-isystem
选项代替-I
。这样,您您不必担心他们的警告。
如果要支持多个平台,则可能需要使用跨平台构建系统生成器,例如cmake。在cmake中,您可以使用SYSTEM选项指定系统包含目录-尽管并非所有系统都必须支持此概念。
答案 1 :(得分:2)
可能有一些方法可以解决带有额外层的编译器检查:
if (std::less<>()(a, LOWER_LIMIT)) // extra function
可能是模板的过度杀伤力:
template <std::size_t Limit>
struct DoesIfLess
{
template <typename F>
void operator ()(std::size_t a, F&&f) {
if (a < Limit) {
std::forward<F>(f)();
}
}
};
template <>
struct DoesIfLess<0>
{
template <typename F>
void operator ()(std::size_t, F&&) {}
};
然后
DoesIfLess<LOWER_LIMIT>(a, [&](){std::cerr << "lower\n"; a = LOWER_LIMIT; });
或使用C ++ 17
if constexpr (LOWER_LIMIT != 0) {
if (a < LOWER_LIMIT) {
std::cerr << "lower\n";
a = LOWER_LIMIT;
}
}
答案 2 :(得分:2)
如果将常量包装在仅返回常量值的不执行任何操作的函数中,警告将消失。
#include <iostream>
const unsigned LOWER_LIMIT = 0;
constexpr auto get_lower_limit() { return LOWER_LIMIT; }
int main(int argc, char* argv[])
{
if (argc > 1) {
unsigned a = atoi(argv[1]);
if (a < get_lower_limit()) {
std::cerr << "lower\n";
a = LOWER_LIMIT;
}
}
}