For this snippet
const std::vector<int> v;
if (v.size() != 1) {} // could call operator!=()
the code complies cleanly even at high warnings levels (all warnings enabled in Visual Studio 2022). However, if I pass the arguments to a function
const auto f = [](auto&& lhs, auto&& rhs) { if (lhs != rhs) {}};
f(v.size(), 1);
the compiler generates a '!=': signed/unsigned mismatch warning.
How can I make the function behave the same way as the "inline" code, i.e., no warning?
Keep in mind that the "real code" is something like
#define f(lhs, rhs) if (lhs != rhs) {}
I'd like to "do the 'right thing'" and replace the macro with a function
temmplate<typename TLhs, typename TRhs>
inline void f(TLhs&& lhs, TRhs&& rhs)
{
if (lhs != rhs) {}
}
In the direct comparison the compiler knows the type of both side of the comparison, and can therefore make sure that the 1 will be an unsigned type of the correct size.
When you call your lambda the type for rhs will be deduced as an int, because that's what 1 really is. And since lhs will be an unsigned type, you get the warning in the comparison when you compare the unsigned size with the (signed) int value 1.
You will get the same problem with any kind of callable object where the compiler must deduce the arguments, like for example function templates:
template<typename T, typename U>
void f(T const& lhs, U const& rhs);
For a function template the solution is simple: Use the same single type for both arguments:
template<typename T>
void f(T const& lhs, T const& rhs);
Move the problem out of your code by calling std::cmp_not_equal
const auto f = [](auto&& lhs, auto&& rhs) {
if (std::cmp_not_equal(lhs, rhs)) { blah blah }
};
This family of functions, added in C++20, is defined in a way that properly compares integer arguments even in the presence of a signed/unsigned mismatch.
Now the Standard library author is responsible for writing "all that template gunk" and all you need to do extra is #include <utility>
For the specific case of assertions, you need a macro anyway to capture information.
#define ASSERT_EQ(actual, expected) do { \
if (lhs == rhs) break; \
log_assertion_failure(__FILE__, __LINE__, #actual, actual, expected); \
} while(0)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With