进行比较时,为什么我必须强制转换为无符号以避免警告

When doing a compare, why must I cast an unsigned to avoid warnings

在下面的示例中,如果我不将 4 转换为无符号,我会收到有关 default.hpp(144) 中的“<=”signed/unsigned 不匹配的警告,然后是更多我不知道的警告跟随。

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <string>

namespace qi = boost::spirit::qi;

typedef std::wstring::const_iterator it_type;

int main()
{
  using qi::_1;
  using boost::spirit::_pass;

  std::wstring testChar(L"450");
  auto f = testChar.begin(), l = testChar.end();

  unsigned pVal[2] = {0, 0};
  qi::uint_parser<unsigned, 10, 1, 1> uint1_p;

  bool retVal = qi::parse(f, l, uint1_p[_pass = _1 <= (unsigned)4] >> qi::uint_, pVal[0], pVal[1]);

  return 0;
}

在这种情况下是否最好始终投射?

在 Visual Studio 2015 年的基础上使用 Boost 1.61.0

您正在将 uint1_p 解析器的属性与 4 进行比较。 uint1_p{} 的属性类型是 unsigned,因此您将 unsigneddecltype(4) 进行比较,即 int.

进行混合符号比较是危险的,编译器会对此发出警告。问题是无符号整数算法是 "contagious",这意味着 4 将被提升为无符号整数,而不是相反。如果你有,这是一个风险。 _1 >= 0 因为它永远不会是假的。

令人印象深刻"error novel"是因为警告出现在语义动作评估的Spirit代码深处。如果你写一些更简单的东西,你会得到同样的信息,比如:

Live On Wandbox

#include <iostream>
int main() {
    for (unsigned i = 10; i >= 0; --i)
        std::cout << i << " ";
}

此程序在 10 次迭代后不会停止。编译器(在本例中为 GCC)警告:

prog.cc:3:29: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits]
     for (unsigned i = 10; i >= 0; --i)
                           ~~^~~~

Q. SHOULD I ALWAYS CAST?

是的。和不。您应该永远不要 使用您编写的 C 风格转换¹。你可以考虑static_cast<unsigned>(4)。但我会简单地写 4u:

bool retVal = qi::parse(f, l, uint1_p[_pass = (_1 <= 4u)] >> qi::uint_, pVal[0], pVal[1]);

¹ 请参阅示例