From ee1d18b538d7d1c60d539e40f8e02f68f72e5d43 Mon Sep 17 00:00:00 2001 From: Ben Deane Date: Thu, 29 Oct 2026 11:29:43 -0600 Subject: [PATCH] :art: Make shrinking transparent to equality comparison Problem: - Shrinking as much as possible should be "invisible", i.e. a shrunk value should be usable like a regular value. As much as possible, regularity operations should be able to treat them the same. Solution: - Make shrunk objects equality comparable with their non-shrunk counterparts. --- include/stdx/type_traits.hpp | 16 ++++++++++++++-- test/ct_string.cpp | 8 ++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/include/stdx/type_traits.hpp b/include/stdx/type_traits.hpp index 967add8..5097b7f 100644 --- a/include/stdx/type_traits.hpp +++ b/include/stdx/type_traits.hpp @@ -221,11 +221,18 @@ namespace detail { template struct shrinkwrap { using is_shrinkwrapped = void; using type = T; + friend constexpr auto operator==(shrinkwrap const &, shrinkwrap const &) + -> bool = default; }; template struct shrinkwrap_value { using is_shrinkwrapped_value = void; + using type = std::remove_cvref_t; constexpr static auto value = V; + + friend constexpr auto operator==(shrinkwrap_value const &, + shrinkwrap_value const &) + -> bool = default; }; template @@ -268,9 +275,7 @@ template consteval auto maybe_expand() -> T; @@ -323,6 +328,13 @@ template constexpr auto expand(T &&t) -> decltype(auto) { template using shrink_t = decltype(shrink()); template using expand_t = decltype(expand()); +template +constexpr auto operator==(T const &t, U const &u) -> bool + requires requires { expand(t) == u; } +{ + return expand(t) == u; +} + STDX_PRAGMA(diagnostic push) #ifdef __clang__ STDX_PRAGMA(diagnostic ignored "-Wunknown-warning-option") diff --git a/test/ct_string.cpp b/test/ct_string.cpp index 92c76b5..1810886 100644 --- a/test/ct_string.cpp +++ b/test/ct_string.cpp @@ -226,6 +226,14 @@ TEST_CASE("named object with shrunk name", "[ct_string]") { STATIC_CHECK(stdx::matching_name_q<"test">::template fn::value); } +TEST_CASE("shrunk ct_string compares equal to ct_string", "[ct_string]") { + using namespace stdx::ct_string_literals; + constexpr auto s = stdx::shrink<"test">(); + STATIC_CHECK(s == "test"_cts); + STATIC_CHECK("test"_cts == s); + STATIC_CHECK(s == s); +} + TEST_CASE("name or type fallback", "[ct_string]") { using namespace stdx::ct_string_literals; using T = stdx::with_name<"test">;