Skip to content

Commit e101a1a

Browse files
committed
🚸 Add operator[] to messages
Problem: - Messages support `get` and `set` but not a natural indexing syntax. Solution: - Add `operator[]` to message, so that the follow work: ```c+++ msg["a"_field] = 42; auto x = msg["a"_field]; ```
1 parent bf31a30 commit e101a1a

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

include/msg/message.hpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,11 +344,36 @@ template <stdx::ct_string Name, typename Access, typename T> struct msg_base {
344344
[[nodiscard]] constexpr auto get(auto f) const {
345345
return Access::get(as_derived().data(), f);
346346
}
347+
347348
constexpr auto set(auto... fs) -> void {
348349
Access::set(as_derived().data(), fs...);
349350
}
350351
constexpr auto set() -> void {}
351352

353+
template <stdx::ct_string N> struct proxy {
354+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members)
355+
msg_base &b;
356+
357+
// NOLINTNEXTLINE(misc-unconventional-assign-operator)
358+
constexpr auto operator=(auto val) const && -> void {
359+
b.set(field_name<N>{} = val);
360+
}
361+
362+
using V = decltype(b.get(std::declval<field_name<N>>()));
363+
364+
// NOLINTNEXTLINE(google-explicit-constructor)
365+
constexpr operator V() const { return b.get(field_name<N>{}); }
366+
};
367+
368+
template <stdx::ct_string N>
369+
[[nodiscard]] constexpr auto operator[](field_name<N> f) const {
370+
return get(f);
371+
}
372+
template <stdx::ct_string N>
373+
[[nodiscard]] constexpr auto operator[](field_name<N>) LIFETIMEBOUND {
374+
return proxy<N>{*this};
375+
}
376+
352377
[[nodiscard]] constexpr auto describe() const {
353378
return Access::describe(as_derived().data());
354379
}

test/msg/message.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,3 +792,17 @@ TEST_CASE("pack appends environments", "[message]") {
792792
using defn = pack<"defn", std::uint8_t, m1, m2>;
793793
STATIC_REQUIRE(custom(defn::env_t{}) == 18);
794794
}
795+
796+
TEST_CASE("read indexing operator on message", "[message]") {
797+
test_msg const msg{};
798+
CHECK(0x80 == msg["id"_field]);
799+
}
800+
801+
TEST_CASE("write indexing operator on message", "[message]") {
802+
test_msg msg{};
803+
bool before = 0 == msg["f1"_field];
804+
CHECK(before);
805+
msg["f1"_field] = 0xba11;
806+
bool after = 0xba11 == msg["f1"_field];
807+
CHECK(after);
808+
}

0 commit comments

Comments
 (0)