New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Compilation error with REQUIRE(std::strong_ordering < 0). #2555
Comments
I looked into this a bit -> it should be fixable, but the fix is going to be annoying because it will require adding bunch of code conditional on C++20. |
From what I've seen, compilers & standard libraries abuse the fact that literal void f(std::nullptr_t);
int main(int argc, char** argv) {
f(0); // correct
f(1); // compiler error
f(argc); // compiler error
} I'm not familiar with Catch2's internals (I just had a quick look at it today), but it might be possible to also abuse this feature to enable the decomposer to detect a literal It would be much more generic, in case people use this "0 to pointer" trick outside the standard library. It doesn't require conditionals on C++20 nor an exhaustive list of classes having such unconventional comparison operators. This trick seems to work on Clang, g++ and MSVC for now at least. Of course it's assuming that the literal zero detector works flawlessly (I can't really tell. This is dark magic for me, I just took the implementation from Clang's source code). If it can match other expressions, it could cause quite a few bugs. |
This actually came up in the lib-ext mailing list. There is no 100% fool-proof way to detect literal 0, which is why comparing orderings with anything that is not literal 0 is UB (ill-formed cannot be standardized without new language features). I poked around a bit, and different stdlibs currently perform the check with different strictness -> e.g. MSVC's I also poked around with the implementation, and I am considering using the zero detection trick, but I have misgivings about it's compilation costs, as it will add a bunch of overloads and TMP to all assertions. It is possible that it will be hidden behind C++20 switch anyway, to avoid imposing the costs on everyone. |
Also I don't see a way to extend the detector hack to handle |
This is primarily done to support new `std::*_ordering` types, but the refactoring also supports any other type with this property. The compilation overhead is surprisingly low. Testing it with clang on a Linux machine, compiling our SelfTest project takes only 2-3% longer with these changes than it takes otherwise. Closes #2555
Bug description
The statement
REQUIRE(x < 0);
fails to compile when x is of type std::strong_ordering from C++20.Reproduction steps
Compile the following code with C++20 flags:
Expected behavior
This test should compile and run successfully.
Platform information:
Catch version: v3.1.0
OS: Windows 10 x64
Compiler: MSVC 19.32.31328 (Visual studio 2022)
First error:
error C2678: binary '<': no operator found which takes a left-hand operand of type 'RhsT' (or there is no acceptable conversion) with [ RhsT=int ]
Full compiler output
OS: Ubuntu 20.04 (virtual machine)
Compiler: g++ 10.3.0
First error:
error: no match for ‘operator<’ (operand types are ‘std::strong_ordering’ and ‘int’)
Full compiler output
Additional context
The std::strong_ordering type is a possible return type of C++20's new three-way comparison operator
<=>
(a.k.a spaceship operator). It should be possible to compare it to literal 0, but comparing it to something else is undefined behaviour. Catch2 coerces the 0 intoint
and looks for an overload of the formoperator<(std::strong_ordering, int)
, but standard libraries don't have to provide one.Workaround
Double parentheses in the
REQUIRE()
statement:The text was updated successfully, but these errors were encountered: