This PR implements C++20’s spaceship operator for wxString.
This is not just nice-to-have, but prevents silent breakage of wxString comparison in user code compiled as C++20 using the recommended configuration of wx, with wxNO_UNSAFE_WXSTRING_CONV defined. Strings end up being compared by their wchar_t* pointer values, not string content. Hence the somewhat inflammatory title of the PR, even though the impact is limited to less commonly needed std containers.
How is this possible? The standard library implements comparison using <=> in C++20 if the operator is available. But wxString doesn’t have it, so it shouldn’t matter for it, right? Surprisingly, that’s not the case:
// this assert, surprisingly, doesn’t fail
static_assert(std::three_way_comparable<wxString>);
Turns out, the spaceship operator is available through implicit conversion to wchar_t pointers:
Consequently, std::tie, std::tuple, std::vector (and who knows what else) comparison uses it for wxString content.
The behavior depends on the macros defined:
wxNO_UNSAFE_WXSTRING_CONV defined, as recommended by wx docs → fails silentlywxNO_IMPLICIT_WXSTRING_CONV_TO_PTR prevents the problem for self-evident reasonsThis also makes it challenging to write a test for the suite — it doesn’t show with wx’s build-time settings, so merely putting the test in there would be a noop. I was using this for testing (and understanding the effect of the macros):
#define wxNO_UNSAFE_WXSTRING_CONV 1
#include <wx/string.h>
TEST_CASE("StringTupleCompare", "[wxString]")
{
wxString a(wxT("bar"));
wxString b(wxT("bar"));
REQUIRE(a == b);
REQUIRE(static_cast<const wchar_t*>(a) != static_cast<const wchar_t*>(b));
CHECK_FALSE(std::tie(a) < std::tie(b));
CHECK_FALSE(std::tie(b) < std::tie(a));
}
IMNSHO this fix needs to be backported to 3.2 too.
https://github.com/wxWidgets/wxWidgets/pull/26306
(1 file)
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
@vslavik pushed 1 commit.
—
View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
(...and force-pushed simplified version that has the advantage of actually working with MSVC)
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
Thanks for fixing this!
Could we perhaps at least add a C++20 build to test that <=> works correctly for wxString? This is what counts, after all...
We can backport it to 3.2 if no problems are found, but I'd like to do at least some testing in master first, so I won't do it immediately.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()