From 2f0c31fbc633496ae7fd55205e0e6c0f831ff172 Mon Sep 17 00:00:00 2001 From: Ben Deane Date: Mon, 1 Sep 2025 11:38:29 -0600 Subject: [PATCH] :sparkles: Add terse udls for size conversion Problem: - It's wordy to type `stdx::sized{42}.in();`. Solution: - Instead, allow `42_z8->z32;` --- docs/utility.adoc | 13 +++++++++++++ include/stdx/utility.hpp | 28 ++++++++++++++++++++++++++++ test/utility.cpp | 15 +++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/docs/utility.adoc b/docs/utility.adoc index 62b7959..f1170a2 100644 --- a/docs/utility.adoc +++ b/docs/utility.adoc @@ -172,6 +172,19 @@ const auto sz = stdx::sized{K}.template in(); The `sized` conversion works either from larger type to smaller type, or the other way around. Or even where the source and destination types are the same. +==== Super-terse size conversion + +Size conversion is conceptually a simple thing, and preferably clear but terse. +To achieve this, with a size known at compile-time we can use a UDL: + +[source,cpp] +---- +using namespace std::literals; +const auto sz = 42_z8->z32; // 42 bytes in std::uint32_t = 11 +---- + +With any combination of `z8`, `z16`, `z32`, `z64`. + === `type_map` `type_map` is a structure designed to allow compile-time lookups of types or diff --git a/include/stdx/utility.hpp b/include/stdx/utility.hpp index a0ab217..11c22b9 100644 --- a/include/stdx/utility.hpp +++ b/include/stdx/utility.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -137,6 +138,33 @@ using sized16 = sized; using sized32 = sized; using sized64 = sized; +template struct udl_sized { + template + constexpr static auto in = detail::size_conversion(N); + + constexpr static auto z8 = in; + constexpr static auto z16 = in; + constexpr static auto z32 = in; + constexpr static auto z64 = in; + + constexpr auto operator->() const -> udl_sized const * { return this; } +}; + +inline namespace literals { +template CONSTEVAL_UDL auto operator""_z8() { + return udl_sized()>{}; +} +template CONSTEVAL_UDL auto operator""_z16() { + return udl_sized()>{}; +} +template CONSTEVAL_UDL auto operator""_z32() { + return udl_sized()>{}; +} +template CONSTEVAL_UDL auto operator""_z64() { + return udl_sized()>{}; +} +} // namespace literals + namespace cxv_detail { struct from_any { // NOLINTNEXTLINE(google-explicit-constructor) diff --git a/test/utility.cpp b/test/utility.cpp index adada35..a7eceec 100644 --- a/test/utility.cpp +++ b/test/utility.cpp @@ -159,6 +159,21 @@ TEST_CASE("sized in (upsize, mod > 1)", "[utility]") { STATIC_REQUIRE(stdx::sized{2}.in() == 2); } +TEST_CASE("terse size conversion with UDLs", "[utility]") { + using namespace stdx::literals; + STATIC_REQUIRE(1_z8->z8 == 1); + STATIC_REQUIRE(2_z8->z16 == 1); + STATIC_REQUIRE(4_z8->z32 == 1); + STATIC_REQUIRE(8_z8->z64 == 1); + + STATIC_REQUIRE(1_z16->z8 == 2); + STATIC_REQUIRE(1_z32->z8 == 4); + STATIC_REQUIRE(1_z64->z8 == 8); + + STATIC_REQUIRE(1_z64->in == 4); + STATIC_REQUIRE(1_z64->in == 2); +} + TEST_CASE("CX_VALUE structural value", "[utility]") { auto x = CX_VALUE(42); STATIC_REQUIRE(x() == 42);