用函数替换宏会导致“有符号/无符号不匹配”警告

Jac*_*own 2 c++ macros function compiler-warnings

对于这个片段

   const std::vector<int> v;
   if (v.size() != 1) {} // could call operator!=()
Run Code Online (Sandbox Code Playgroud)

即使在高警告级别下,代码也完全符合要求(所有警告在 Visual Studio 2022 中启用)。但是,如果我将参数传递给函数

   const auto f = [](auto&& lhs, auto&& rhs) { if (lhs != rhs) {}};
   f(v.size(), 1);
Run Code Online (Sandbox Code Playgroud)

编译器生成“!=”:有符号/无符号不匹配警告。

如何使该函数的行为与“内联”代码相同,即没有警告?


请记住,“真正的代码”类似于

#define f(lhs, rhs) if (lhs != rhs) {}
Run Code Online (Sandbox Code Playgroud)

我想“做‘正确的事’”并用函数替换宏

temmplate<typename TLhs, typename TRhs>
inline void f(TLhs&& lhs, TRhs&& rhs)
{
   if (lhs != rhs) {}
}
Run Code Online (Sandbox Code Playgroud)

Som*_*ude 5

在直接比较中,编译器知道比较双方的类型,因此可以确保将1是正确大小的无符号类型。

当您调用 lambda 时, for 的类型rhs将被推导出为 an int,因为这才是1真正的类型。由于将是无符号类型,因此当您将无符号大小与(有符号)值lhs进行比较时,您会在比较中收到警告。int1


对于任何类型的可调用对象,编译器必须推断出参数,您都会遇到同样的问题,例如函数模板:

template<typename T, typename U>
void f(T const& lhs, U const& rhs);
Run Code Online (Sandbox Code Playgroud)

对于函数模板,解决方案很简单:对两个参数使用相同的单一类型:

template<typename T>
void f(T const& lhs, T const& rhs);
Run Code Online (Sandbox Code Playgroud)