From d3eb6f534ac733ca52978b9f734821b7609d134f Mon Sep 17 00:00:00 2001 From: Ben Deane Date: Tue, 4 Feb 2025 09:59:21 -0700 Subject: [PATCH] :art: Allow "relaxed" fields to have defaults, matchers etc Problem: - Unlocated ("relaxed") fields can't have matchers and default values easily specified. Solution: - Move the location aliases into `detail::field_t`; use the "builder pattern". --- include/msg/field.hpp | 27 ++++++++++++++++----------- test/msg/relaxed_message.cpp | 22 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/include/msg/field.hpp b/include/msg/field.hpp index e332330e..49169551 100644 --- a/include/msg/field.hpp +++ b/include/msg/field.hpp @@ -389,13 +389,19 @@ concept compatible_with_default = D::template is_compatible_value; template struct field_id_t {}; +template struct sort_key_t { + constexpr static auto sort_key = std::min({Ats.sort_key()...}); +}; +template <> struct sort_key_t<> {}; + template , match::matcher M = match::always_t, at... Ats> requires std::is_trivially_copyable_v class field_t : public field_spec_t>, public detail::locator_for, - public Default { + public Default, + public sort_key_t { using spec_t = field_spec_t>; using locator_t = detail::locator_for; @@ -412,7 +418,6 @@ class field_t : public field_spec_t>, using field_id = field_id_t; using value_type = T; using matcher_t = M; - constexpr static auto sort_key = std::min({Ats.sort_key()...}); template [[nodiscard]] constexpr static auto extract(R &&r) -> value_type { @@ -511,6 +516,12 @@ class field_t : public field_spec_t>, using shifted_by = field_t(N))...>; + template + using located = field_t; + + constexpr static auto bitsize = sizeof(T) * CHAR_BIT; + using default_located = located; + // ====================================================================== // legacy aliases template using WithMatch = with_matcher; @@ -527,13 +538,7 @@ class field_t : public field_spec_t>, template , match::matcher M = match::always_t> -struct field { - template - using located = detail::field_t< - decltype(stdx::ct_string_to_type()), T, - Default, M, Ats...>; - - constexpr static auto bitsize = sizeof(T) * CHAR_BIT; - using default_located = located; -}; +using field = detail::field_t< + decltype(stdx::ct_string_to_type()), T, Default, + M>; } // namespace msg diff --git a/test/msg/relaxed_message.cpp b/test/msg/relaxed_message.cpp index 06ed11d4..0a36dd69 100644 --- a/test/msg/relaxed_message.cpp +++ b/test/msg/relaxed_message.cpp @@ -43,3 +43,25 @@ TEST_CASE("message with no automatically packed fields", "[relaxed_message]") { using expected_defn = msg::message<"msg", fixed_f>; static_assert(std::is_same_v); } + +TEST_CASE("auto field with default value", "[relaxed_message]") { + using defn = relaxed_message<"msg", auto_f1::with_default<42>>; + using expected_defn = msg::message< + "msg", auto_f1::located::with_default<42>>; + static_assert(std::is_same_v); +} + +TEST_CASE("auto field with const default value", "[relaxed_message]") { + using defn = relaxed_message<"msg", auto_f1::with_const_default<42>>; + using expected_defn = + msg::message<"msg", auto_f1::located::with_const_default<42>>; + static_assert(std::is_same_v); +} + +TEST_CASE("auto field without default value", "[relaxed_message]") { + using defn = relaxed_message<"msg", auto_f1::without_default>; + using expected_defn = msg::message< + "msg", auto_f1::located::without_default>; + static_assert(std::is_same_v); +}