From bfb27b4d9a1471e33136ba8fad1bef5b9ede09e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dr=2E=20Patrick=20Urbanke=20=28=E5=8A=89=E8=87=AA=E6=88=90?= =?UTF-8?q?=29?= Date: Wed, 22 Jul 2026 23:58:02 +0200 Subject: [PATCH] Added the arrow operator; fixes #699 --- docs/commented.md | 2 +- docs/default_val.md | 2 +- docs/flatten_structs.md | 2 +- docs/generic.md | 2 +- docs/json_schema.md | 4 ++-- docs/named_tuple.md | 2 +- docs/number_systems.md | 2 +- docs/supported_formats/xml.md | 2 +- docs/timestamps.md | 2 +- docs/validating_numbers.md | 2 +- include/rfl/Attribute.hpp | 8 ++++++++ include/rfl/Binary.hpp | 8 ++++++++ include/rfl/Commented.hpp | 8 ++++++++ include/rfl/DefaultVal.hpp | 8 ++++++++ include/rfl/Deprecated.hpp | 8 ++++++++ include/rfl/Description.hpp | 8 ++++++++ include/rfl/Field.hpp | 8 ++++++++ include/rfl/Flatten.hpp | 8 ++++++++ include/rfl/Hex.hpp | 8 ++++++++ include/rfl/Oct.hpp | 8 ++++++++ include/rfl/Positional.hpp | 8 ++++++++ include/rfl/Rename.hpp | 8 ++++++++ include/rfl/Short.hpp | 8 ++++++++ include/rfl/Timestamp.hpp | 8 ++++++++ include/rfl/Validator.hpp | 8 ++++++++ include/rfl/internal/Skip.hpp | 8 ++++++++ 26 files changed, 139 insertions(+), 11 deletions(-) diff --git a/docs/commented.md b/docs/commented.md index 494bceee1..797fc86d3 100644 --- a/docs/commented.md +++ b/docs/commented.md @@ -66,7 +66,7 @@ This will result in the following XML: `rfl::Commented` provides several ways to access and modify the underlying value and the comment: -- `.get()`, `.value()`, `operator()()` — access the underlying value (const and non-const overloads). +- `.get()`, `.value()`, `operator()()`, `operator*()`, `operator->()` — access the underlying value (const and non-const overloads). - `.comment()` — returns an `std::optional` containing the comment. - `.add_comment(std::string)` — sets or updates the comment. - `.set(...)`, `operator=(...)` — assign the underlying value. diff --git a/docs/default_val.md b/docs/default_val.md index 7801dfb6b..ced77a072 100644 --- a/docs/default_val.md +++ b/docs/default_val.md @@ -25,7 +25,7 @@ std::string s = p.last_name.value(); API convenience: -- .get(), .value(), operator()(), operator*() — access the underlying value (const and non-const overloads). +- .get(), .value(), operator()(), operator*(), operator->() — access the underlying value (const and non-const overloads). - set(...) — assign underlying value. ## JSON behaviour diff --git a/docs/flatten_structs.md b/docs/flatten_structs.md index 6eb6bd7d6..b6c0b1baf 100644 --- a/docs/flatten_structs.md +++ b/docs/flatten_structs.md @@ -70,4 +70,4 @@ This flattens all fields into a single JSON object: ## API convenience -`rfl::Flatten` behaves like a thin wrapper around the underlying type. You can access the underlying value using `.get()`, `.value()`, `operator()()`, or `operator*()` (const and non-const overloads). +`rfl::Flatten` behaves like a thin wrapper around the underlying type. You can access the underlying value using `.get()`, `.value()`, `operator()()`, `operator*()`, or `operator->()` (const and non-const overloads). diff --git a/docs/generic.md b/docs/generic.md index 8fde288a7..30f8478ab 100644 --- a/docs/generic.md +++ b/docs/generic.md @@ -55,7 +55,7 @@ The resulting JSON strings looks as follows: `rfl::Generic` contains some convenience methods that allow you to handle parsed data: -You can retrieve the underlying `std::variant` using `.get()`, `.value()`, `operator()()`, or `operator*()`. This then allows you to handle all possible seven cases using the [visitor pattern](https://en.cppreference.com/w/cpp/utility/variant/visit). +You can retrieve the underlying `std::variant` using `.get()`, `.value()`, `operator()()`, `operator*()`, or `operator->()`. This then allows you to handle all possible seven cases using the [visitor pattern](https://en.cppreference.com/w/cpp/utility/variant/visit). If you have a guess what the types of a particular field might be, you can use any of the seven convenience methods `.to_array()`, `.to_bool()`, `.to_double()`, `.to_int()`, `.to_null()`, `.to_object()`, `.to_string()`. Each of these methods will return an `rfl::Result<...>` with the corresponding type, if the `rfl::Generic` does indeed contain such a type. diff --git a/docs/json_schema.md b/docs/json_schema.md index 4bd0720ec..ad97d630b 100644 --- a/docs/json_schema.md +++ b/docs/json_schema.md @@ -139,7 +139,7 @@ const std::string json_schema = rfl::json::to_schema(rfl::json::pretty); } ``` -`rfl::Description` behaves like a thin wrapper around the underlying type. Much like `rfl::Field`, you can access the underlying value using `.get()`, `.value()`, `operator()()`, or `operator*()` (const and non-const overloads). +`rfl::Description` behaves like a thin wrapper around the underlying type. Much like `rfl::Field`, you can access the underlying value using `.get()`, `.value()`, `operator()()`, `operator*()`, or `operator->()` (const and non-const overloads). You also add a description to the entire JSON schema: @@ -243,4 +243,4 @@ const std::string json_schema = rfl::json::to_schema(rfl::json::pretty); } ``` -`rfl::Deprecated` behaves like a thin wrapper around the underlying type, just like `rfl::Description`. You can access the underlying value using `.get()`, `.value()`, `operator()()`, or the assignment operator. +`rfl::Deprecated` behaves like a thin wrapper around the underlying type, just like `rfl::Description`. You can access the underlying value using `.get()`, `.value()`, `operator()()`, `operator*()`, `operator->()`, or the assignment operator. diff --git a/docs/named_tuple.md b/docs/named_tuple.md index 64da742c6..355836de8 100644 --- a/docs/named_tuple.md +++ b/docs/named_tuple.md @@ -110,7 +110,7 @@ person.apply([](const auto& f) { ### `rfl::Field` API convenience -`rfl::Field` behaves like a thin wrapper around the underlying type. You can access the underlying value using `.get()`, `.value()`, `operator()()`, or `operator*()` (const and non-const overloads). +`rfl::Field` behaves like a thin wrapper around the underlying type. You can access the underlying value using `.get()`, `.value()`, `operator()()`, `operator*()`, or `operator->()` (const and non-const overloads). ``` ### Monadic operations: `.transform` and `.and_then` diff --git a/docs/number_systems.md b/docs/number_systems.md index c39310528..57a35ffa0 100644 --- a/docs/number_systems.md +++ b/docs/number_systems.md @@ -25,6 +25,6 @@ This results in the following JSON: Note that the contained type must be integral for `rfl::Hex` and `rfl::Oct`. For `rfl::Binary`, it must be unsigned. Moreover, the number of digits for `rfl::Binary` will be determined by the bitsize of the type. -You can access the contained value using `.value()`, `.get()`, `operator()()`, or `operator*()` (const and non-const overloads). +You can access the contained value using `.value()`, `.get()`, `operator()()`, `operator*()`, or `operator->()` (const and non-const overloads). You can produce the string representation using `.str()`. diff --git a/docs/supported_formats/xml.md b/docs/supported_formats/xml.md index cf1ddf41a..e9e4d4009 100644 --- a/docs/supported_formats/xml.md +++ b/docs/supported_formats/xml.md @@ -137,7 +137,7 @@ This will result in the following XML string: Note that only boolean values, string values, integral values or floating point values can be represented as attributes. -`rfl::Attribute` behaves like a thin wrapper around the underlying type. Much like `rfl::Field`, you can access the underlying value using `.get()`, `.value()`, `operator()()`, or `operator*()` (const and non-const overloads). +`rfl::Attribute` behaves like a thin wrapper around the underlying type. Much like `rfl::Field`, you can access the underlying value using `.get()`, `.value()`, `operator()()`, `operator*()`, or `operator->()` (const and non-const overloads). There also is a special field name called `xml_content` to be used when you want a value directly inserted into the content. Again, only boolean values, string values, integral values or floating point values can be represented this way: diff --git a/docs/timestamps.md b/docs/timestamps.md index 6f1474eaa..ca0d47f3d 100644 --- a/docs/timestamps.md +++ b/docs/timestamps.md @@ -27,7 +27,7 @@ const auto person1 = Person{.birthday = "1970-01-01"}; const auto person2 = Person{.birthday = std::tm{...}}; ``` -You can access the underlying `std::tm` struct using the `.tm()`, `.get()`, `.value()`, `operator()()`, or `operator*()` method (const and non-const overloads). You can generate the string representation using the `.str()` method. +You can access the underlying `std::tm` struct using the `.tm()`, `.get()`, `.value()`, `operator()()`, `operator*()`, or `operator->()` method (const and non-const overloads). You can generate the string representation using the `.str()` method. ```cpp const std::tm birthday = person1.birthday.tm(); diff --git a/docs/validating_numbers.md b/docs/validating_numbers.md index c39c9d733..f72aca2ef 100644 --- a/docs/validating_numbers.md +++ b/docs/validating_numbers.md @@ -10,7 +10,7 @@ using IntGreaterThan10 = rfl::Validator>; When you then use the type `IntGreaterThan10` inside you `rfl::Field`, the condition will be automatically validated. -The underlying value can be retrieved using the `.get()`, `.value()`, `operator()()`, or `operator*()` method (const and non-const overloads). +The underlying value can be retrieved using the `.get()`, `.value()`, `operator()()`, `operator*()`, or `operator->()` method (const and non-const overloads). The current conditions are currently supported by reflect-cpp: diff --git a/include/rfl/Attribute.hpp b/include/rfl/Attribute.hpp index c9ea66fb5..e277323bf 100644 --- a/include/rfl/Attribute.hpp +++ b/include/rfl/Attribute.hpp @@ -109,6 +109,14 @@ struct Attribute { /// @return Const reference to the stored value const Type& operator()() const noexcept { return value_; } + /// Pointer to the underlying value. + /// @return Pointer to the stored value + Type* operator->() noexcept { return &value_; } + + /// Pointer to the underlying value (const). + /// @return Const pointer to the stored value + const Type* operator->() const noexcept { return &value_; } + /// Assigns a new value. /// @param _value The value to assign /// @return Reference to this Attribute diff --git a/include/rfl/Binary.hpp b/include/rfl/Binary.hpp index 9dc81a657..a7b6a75b4 100644 --- a/include/rfl/Binary.hpp +++ b/include/rfl/Binary.hpp @@ -109,6 +109,14 @@ struct Binary { /// @return Const reference to the stored value const Type& operator()() const noexcept { return value_; } + /// Pointer to the underlying value. + /// @return Pointer to the stored value + Type* operator->() noexcept { return &value_; } + + /// Pointer to the underlying value (const). + /// @return Const pointer to the stored value + const Type* operator->() const noexcept { return &value_; } + /// Assigns a new integer value. /// @param _value The value to assign /// @return Reference to this Binary diff --git a/include/rfl/Commented.hpp b/include/rfl/Commented.hpp index 8d5e87568..def8e58e4 100644 --- a/include/rfl/Commented.hpp +++ b/include/rfl/Commented.hpp @@ -127,6 +127,14 @@ struct Commented { /// @return Const reference to the stored value const Type& operator()() const { return value_; } + /// Pointer to the underlying value. + /// @return Pointer to the stored value + Type* operator->() { return &value_; } + + /// Pointer to the underlying value (const). + /// @return Const pointer to the stored value + const Type* operator->() const { return &value_; } + /// Dereference operator - returns the underlying value. /// @return Reference to the stored value Type& operator*() { return value_; } diff --git a/include/rfl/DefaultVal.hpp b/include/rfl/DefaultVal.hpp index e1692253a..630a3f5bd 100644 --- a/include/rfl/DefaultVal.hpp +++ b/include/rfl/DefaultVal.hpp @@ -106,6 +106,14 @@ struct DefaultVal { /// @return Const reference to the stored value const Type& operator()() const noexcept { return value_; } + /// Pointer to the underlying value. + /// @return Pointer to the stored value + Type* operator->() noexcept { return &value_; } + + /// Pointer to the underlying value (const). + /// @return Const pointer to the stored value + const Type* operator->() const noexcept { return &value_; } + /// Assigns a new value. /// @param _value The value to assign /// @return Reference to this DefaultVal diff --git a/include/rfl/Deprecated.hpp b/include/rfl/Deprecated.hpp index 340534923..e1cd712fb 100644 --- a/include/rfl/Deprecated.hpp +++ b/include/rfl/Deprecated.hpp @@ -114,6 +114,14 @@ struct Deprecated { /// @return Const reference to the stored value const Type& operator()() const { return value_; } + /// Pointer to the underlying value. + /// @return Pointer to the stored value + Type* operator->() { return &value_; } + + /// Pointer to the underlying value (const). + /// @return Const pointer to the stored value + const Type* operator->() const { return &value_; } + /// Assigns a new value. /// @param _value The value to assign /// @return Reference to this Deprecated diff --git a/include/rfl/Description.hpp b/include/rfl/Description.hpp index d5f1faed7..37fc84092 100644 --- a/include/rfl/Description.hpp +++ b/include/rfl/Description.hpp @@ -120,6 +120,14 @@ struct Description { /// @return Const reference to the stored value const Type& operator()() const noexcept { return value_; } + /// Pointer to the underlying value. + /// @return Pointer to the stored value + Type* operator->() noexcept { return &value_; } + + /// Pointer to the underlying value (const). + /// @return Const pointer to the stored value + const Type* operator->() const noexcept { return &value_; } + /// Assigns a new value. /// @param _value The value to assign /// @return Reference to this Description diff --git a/include/rfl/Field.hpp b/include/rfl/Field.hpp index 4c9e3c967..9ea272742 100644 --- a/include/rfl/Field.hpp +++ b/include/rfl/Field.hpp @@ -117,6 +117,14 @@ struct Field { /// @return Const reference to the stored value const Type& operator()() const noexcept { return value_; } + /// Pointer to the underlying value. + /// @return Pointer to the stored value + Type* operator->() noexcept { return &value_; } + + /// Pointer to the underlying value (const). + /// @return Const pointer to the stored value + const Type* operator->() const noexcept { return &value_; } + /// Assigns a new value to the field. /// @param _value The value to assign /// @return Reference to this field diff --git a/include/rfl/Flatten.hpp b/include/rfl/Flatten.hpp index c4f9b09fe..bb2e63ddb 100644 --- a/include/rfl/Flatten.hpp +++ b/include/rfl/Flatten.hpp @@ -82,6 +82,14 @@ struct Flatten { /// Returns the underlying object. const Type& operator()() const noexcept { return value_; } + /// Pointer to the underlying value. + /// @return Pointer to the stored value + Type* operator->() noexcept { return &value_; } + + /// Pointer to the underlying value (const). + /// @return Const pointer to the stored value + const Type* operator->() const noexcept { return &value_; } + /// Returns the underlying object. Type& value() noexcept { return value_; } diff --git a/include/rfl/Hex.hpp b/include/rfl/Hex.hpp index 70eafad62..db15788cc 100644 --- a/include/rfl/Hex.hpp +++ b/include/rfl/Hex.hpp @@ -106,6 +106,14 @@ struct Hex { /// @return Const reference to the stored value const Type& operator()() const noexcept { return value_; } + /// Pointer to the underlying value. + /// @return Pointer to the stored value + Type* operator->() noexcept { return &value_; } + + /// Pointer to the underlying value (const). + /// @return Const pointer to the stored value + const Type* operator->() const noexcept { return &value_; } + /// Assigns a new integer value. /// @param _value The value to assign /// @return Reference to this Hex diff --git a/include/rfl/Oct.hpp b/include/rfl/Oct.hpp index 20e0c3306..8fedd003a 100644 --- a/include/rfl/Oct.hpp +++ b/include/rfl/Oct.hpp @@ -70,6 +70,14 @@ struct Oct { /// Returns the underlying object. const Type& operator()() const noexcept { return value_; } + /// Pointer to the underlying value. + /// @return Pointer to the stored value + Type* operator->() noexcept { return &value_; } + + /// Pointer to the underlying value (const). + /// @return Const pointer to the stored value + const Type* operator->() const noexcept { return &value_; } + /// Assigns the underlying object. auto& operator=(const Type& _value) { value_ = _value; diff --git a/include/rfl/Positional.hpp b/include/rfl/Positional.hpp index 76a94f3d9..5540e03dc 100644 --- a/include/rfl/Positional.hpp +++ b/include/rfl/Positional.hpp @@ -97,6 +97,14 @@ struct Positional { /// @return Const reference to the stored value const Type& operator()() const noexcept { return value_; } + /// Pointer to the underlying value. + /// @return Pointer to the stored value + Type* operator->() noexcept { return &value_; } + + /// Pointer to the underlying value (const). + /// @return Const pointer to the stored value + const Type* operator->() const noexcept { return &value_; } + /// Assigns a new value. /// @param _value The value to assign /// @return Reference to this Positional diff --git a/include/rfl/Rename.hpp b/include/rfl/Rename.hpp index bc8418819..c92ecf5fb 100644 --- a/include/rfl/Rename.hpp +++ b/include/rfl/Rename.hpp @@ -118,6 +118,14 @@ struct Rename { /// @return Const reference to the stored value const Type& operator()() const noexcept { return value_; } + /// Pointer to the underlying value. + /// @return Pointer to the stored value + Type* operator->() noexcept { return &value_; } + + /// Pointer to the underlying value (const). + /// @return Const pointer to the stored value + const Type* operator->() const noexcept { return &value_; } + /// Assigns a new value. /// @param _value The value to assign /// @return Reference to this Rename diff --git a/include/rfl/Short.hpp b/include/rfl/Short.hpp index 07f0b94d7..b4fb59afe 100644 --- a/include/rfl/Short.hpp +++ b/include/rfl/Short.hpp @@ -108,6 +108,14 @@ struct Short { /// @return Const reference to the underlying value. const Type& operator()() const noexcept { return value_; } + /// @brief Pointer to the underlying value. + /// @return Pointer to the underlying value. + Type* operator->() noexcept { return &value_; } + + /// @brief Pointer to the underlying value (const). + /// @return Const pointer to the underlying value. + const Type* operator->() const noexcept { return &value_; } + /// @brief Assigns a new value to the underlying object. /// @param _value The value to assign. /// @return Reference to this Short. diff --git a/include/rfl/Timestamp.hpp b/include/rfl/Timestamp.hpp index a43c07efe..5c15122b1 100644 --- a/include/rfl/Timestamp.hpp +++ b/include/rfl/Timestamp.hpp @@ -111,6 +111,14 @@ class Timestamp { /// Returns the underlying object. const std::tm& operator()() const noexcept { return tm_; } + /// Pointer to the underlying object. + /// @return Pointer to the stored std::tm + std::tm* operator->() noexcept { return &tm_; } + + /// Pointer to the underlying object (const). + /// @return Const pointer to the stored std::tm + const std::tm* operator->() const noexcept { return &tm_; } + /// Returns the underlying object. std::tm& value() noexcept { return tm_; } diff --git a/include/rfl/Validator.hpp b/include/rfl/Validator.hpp index 7ced2daaf..b10c543dd 100644 --- a/include/rfl/Validator.hpp +++ b/include/rfl/Validator.hpp @@ -160,6 +160,14 @@ struct Validator { /// Returns the underlying object. const T& operator()() const noexcept { return value_; } + /// Pointer to the underlying value. + /// @return Pointer to the stored value + T* operator->() noexcept { return &value_; } + + /// Pointer to the underlying value (const). + /// @return Const pointer to the stored value + const T* operator->() const noexcept { return &value_; } + /// Exposes the underlying value. T& value() noexcept { return value_; } diff --git a/include/rfl/internal/Skip.hpp b/include/rfl/internal/Skip.hpp index d998ef5a2..442683dec 100644 --- a/include/rfl/internal/Skip.hpp +++ b/include/rfl/internal/Skip.hpp @@ -78,6 +78,14 @@ class Skip { /// Returns the underlying object. const Type& operator()() const noexcept { return value_; } + /// Pointer to the underlying value. + /// @return Pointer to the stored value + Type* operator->() noexcept { return &value_; } + + /// Pointer to the underlying value (const). + /// @return Const pointer to the stored value + const Type* operator->() const noexcept { return &value_; } + /// Assigns the underlying object. auto& operator=(const Type& _value) { value_ = _value;