-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Change _Literal_zero constructor to use pointer to _Literal_zero #4332
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
Conversation
This means that `std::is_constructible_v<_Literal_zero, int>` is now false, and thus libraries like Catch2 can detect the difference between a type comparable with `int`, and type comparable only with literal `0`. This then lets it handle expressions like `(a <=> b) == 0` inside `REQUIRE`.
|
I would've liked to add some static asserts as tests, but I didn't see a place to add them to in the tests. I think it is fine to leave it as is, or, if you give me a pointer to where the tests should go, I will add them. |
|
48 tests failed. (https://dev.azure.com/vclibs/STL/_build/results?buildId=15956&view=ms.vss-test-web.build-test-results-tab) |
|
The change can be regressive because it expects treating On the other hand, this PR, with ambiguity resolved and Perhaps we should ask MSVC/Clang frontend teams to add an internal type which can only be initialized with literal We can furtherly constrain the deleted overload to resolve ambiguity. diff --git a/stl/inc/compare b/stl/inc/compare
index e35d1a3a..aafe073f 100644
--- a/stl/inc/compare
+++ b/stl/inc/compare
@@ -25,16 +25,22 @@ _STL_DISABLE_CLANG_WARNINGS
#undef new
_STD_BEGIN
+_EXPORT_STD struct strong_ordering;
+_EXPORT_STD struct weak_ordering;
+_EXPORT_STD struct partial_ordering;
+
void _Literal_zero_is_expected();
struct _Literal_zero {
- template <class _Ty, enable_if_t<is_same_v<_Ty, int>, int> = 0>
- consteval _Literal_zero(_Ty _Zero) noexcept {
+ consteval _Literal_zero(_Literal_zero* _Zero) noexcept {
// Can't use _STL_VERIFY because this is a core header
- if (_Zero != 0) {
+ if (_Zero != nullptr) {
_Literal_zero_is_expected();
}
}
+ template <class _Ty,
+ enable_if_t<!_Is_any_of_v<_Ty, int, strong_ordering, weak_ordering, partial_ordering>, int> = 0>
+ _Literal_zero(_Ty) = delete;
};
using _Compare_t = signed char;
|
|
I'm not convinced that the ambiguity can be properly resolved here (what if someone derives from a Standard comparison category?). I also believe that our current implementation is conforming, and that Catch2 is relying on a non-Standard assumption here. Marking this as "decision needed"; I'll bring this up at the next weekly maintainer meeting on Wednesday. |
This is correct, however the assumption, or rather the effect of it, is a useful one, and works for libc++ and libstdc++. |
The idea of a magic compiler type (or type attribute) seems to be a promising solution. |
|
I don't really foresee the MSVC compiler frontend team having capacity to implement such magic any time soon. |
|
We talked about this at our weekly maintainer meeting and agree that this explicitly falls under our Non-Goals as a non-Standard extension. Thanks for looking into this. |
|
Very well. I do want to point out that this change is not a non-standard extension. The PR would change the implementation of an unspecified type to align it with the implementations in libstdc++ and libc++ and with the implementation in Microsoft/STL from ~10 months ago. |
|
Also since I am having a related discussion in parallel somewhere else, I found that the change made in #3581 broke other people back in November and there is a devcom ticket about it. It boils down to |
#include <compare>
template<typename T, typename U>
constexpr bool not_equal(T lhs, U rhs)
requires(requires(T lhs, U rhs) { lhs != rhs; })
{
return lhs != rhs;
}
template<typename T, typename U>
constexpr bool not_equal(T lhs, U rhs)
requires(!requires(T lhs, U rhs) { lhs != rhs; })
{
return false;
}
int main() {
constexpr int int_zero = 0;
constexpr unsigned int unsigned_zero = 0;
constexpr auto ordering = 1 <=> 1;
constexpr bool b = not_equal(ordering, unsigned_zero);
constexpr bool b = not_equal(ordering, int_zero); //FAILS ON MSVC Stdlib
return b == false;
}
https://godbolt.org/z/s7vbh1PPf Asking if an ordering is comparable with an int ought to be an answerable question. |
|
I created an issue about it. |
This means that
std::is_constructible_v<_Literal_zero, int>is now false, and thus libraries like Catch2 can detect the difference between a type comparable withint, and type comparable only with literal0. This then lets it handle expressions like(a <=> b) == 0insideREQUIRE.