From f60fdfe7d0ab6cc9ed9180d671247602d824a963 Mon Sep 17 00:00:00 2001 From: GregTheMadMonk Date: Tue, 19 Aug 2025 13:13:14 +0300 Subject: [PATCH 1/3] Optimize error construction with rvalues&prealloc --- include/rfl/Result.hpp | 7 +++++++ include/rfl/parsing/Parser_rfl_variant.hpp | 3 ++- include/rfl/parsing/Parser_variant.hpp | 3 ++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/rfl/Result.hpp b/include/rfl/Result.hpp index 33b0925b..a7422203 100644 --- a/include/rfl/Result.hpp +++ b/include/rfl/Result.hpp @@ -21,10 +21,13 @@ namespace rfl { class Error { public: Error(const std::string& _what) : what_(_what) {} + Error(std::string&& _what) : what_(std::move(_what)) {} Error(const Error& e) = default; + Error(Error&& e) = default; Error& operator=(const Error&) = default; + Error& operator=(Error&&) = default; /// Returns the error message, equivalent to .what() in std::exception. const std::string& what() const { return what_; } @@ -431,6 +434,10 @@ inline Unexpected error(const std::string& _what) { return Unexpected(Error(_what)); } +inline Unexpected error(std::string&& _what) { + return Unexpected(Error(std::move(_what))); +} + /// Shorthand for unexpected error. inline Unexpected error(const Error& _err) { return Unexpected(_err); diff --git a/include/rfl/parsing/Parser_rfl_variant.hpp b/include/rfl/parsing/Parser_rfl_variant.hpp index c205f60f..3308e87a 100644 --- a/include/rfl/parsing/Parser_rfl_variant.hpp +++ b/include/rfl/parsing/Parser_rfl_variant.hpp @@ -68,6 +68,7 @@ class Parser, ProcessorsType> { } else { std::optional> result; std::vector errors; + errors.reserve(sizeof...(AlternativeTypes)); read_variant( _r, _var, &result, &errors, std::make_integer_sequence()); @@ -187,7 +188,7 @@ class Parser, ProcessorsType> { if (res) { *_result = std::move(*res); } else { - _errors->emplace_back(res.error()); + _errors->emplace_back(std::move(res.error())); } } } diff --git a/include/rfl/parsing/Parser_variant.hpp b/include/rfl/parsing/Parser_variant.hpp index ac05e08d..dbe1a55b 100644 --- a/include/rfl/parsing/Parser_variant.hpp +++ b/include/rfl/parsing/Parser_variant.hpp @@ -85,6 +85,7 @@ class Parser, ProcessorsType> { } else { std::optional> result; std::vector errors; + errors.reserve(sizeof...(AlternativeTypes)); read_variant( _r, _var, &result, &errors, std::make_integer_sequence()); @@ -215,7 +216,7 @@ class Parser, ProcessorsType> { if (res) { *_result = std::move(*res); } else { - _errors->emplace_back(res.error()); + _errors->emplace_back(std::move(res.error())); } } } From 1e111a28236f4a36eac457cde598d22efd104947 Mon Sep 17 00:00:00 2001 From: GregTheMadMonk Date: Tue, 19 Aug 2025 13:23:34 +0300 Subject: [PATCH 2/3] Perf: perfect forwarding improvements --- include/rfl/parsing/MapReader.hpp | 12 +++++++----- include/rfl/parsing/Parser_default.hpp | 10 ++++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/include/rfl/parsing/MapReader.hpp b/include/rfl/parsing/MapReader.hpp index 3ee890fa..5fe07902 100644 --- a/include/rfl/parsing/MapReader.hpp +++ b/include/rfl/parsing/MapReader.hpp @@ -55,11 +55,13 @@ class MapReader { } } - Result> make_key(auto& _pair) const noexcept { + Result> make_key(auto&& _pair) const noexcept { + static_assert(std::is_rvalue_reference_v, "Expected an rvalue"); const auto to_pair = - [&](auto _key) -> Result> { + [&](auto&& _key) -> Result> { try { - return std::make_pair(KeyType(std::move(_key)), + using K = decltype(_key); + return std::make_pair(KeyType(std::forward(_key)), std::move(_pair.second)); } catch (std::exception& e) { return error(e.what()); @@ -77,7 +79,7 @@ class MapReader { std::is_floating_point_v) { return key_to_numeric(_pair).and_then(to_pair); } else { - return to_pair(_pair.first); + return to_pair(std::move(_pair.first)); } } else { @@ -89,7 +91,7 @@ class MapReader { const std::string_view& _name, const InputVarType& _var) const noexcept { const auto to_pair = [&](ValueType&& _val) { auto pair = std::make_pair(std::string(_name), std::move(_val)); - return make_key(pair); + return make_key(std::move(pair)); }; return Parser, ProcessorsType>::read( *r_, _var) diff --git a/include/rfl/parsing/Parser_default.hpp b/include/rfl/parsing/Parser_default.hpp index 700cdf0a..06eaedbd 100644 --- a/include/rfl/parsing/Parser_default.hpp +++ b/include/rfl/parsing/Parser_default.hpp @@ -46,9 +46,10 @@ struct Parser { /// Expresses the variables as type T. static Result read(const R& _r, const InputVarType& _var) noexcept { if constexpr (internal::has_read_reflector) { - const auto wrap_in_t = [](auto _named_tuple) -> Result { + const auto wrap_in_t = [](auto&& _named_tuple) -> Result { try { - return Reflector::to(_named_tuple); + using NT = decltype(_named_tuple); + return Reflector::to(std::forward(_named_tuple)); } catch (std::exception& e) { return error(e.what()); } @@ -67,9 +68,10 @@ struct Parser { } else { if constexpr (internal::has_reflection_type_v) { using ReflectionType = std::remove_cvref_t; - const auto wrap_in_t = [](auto _named_tuple) -> Result { + const auto wrap_in_t = [](auto&& _named_tuple) -> Result { try { - return T{std::move(_named_tuple)}; + using NT = decltype(_named_tuple); + return T{std::forward(_named_tuple)}; } catch (std::exception& e) { return error(e.what()); } From 6e6aff8a868a0448f8a491ff135a674841a2fd90 Mon Sep 17 00:00:00 2001 From: "Dr. Patrick Urbanke" Date: Mon, 25 Aug 2025 01:04:59 +0200 Subject: [PATCH 3/3] Declare err using const auto --- include/rfl/parsing/NamedTupleParser.hpp | 28 ++++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/include/rfl/parsing/NamedTupleParser.hpp b/include/rfl/parsing/NamedTupleParser.hpp index 88200a27..b1cdfafd 100644 --- a/include/rfl/parsing/NamedTupleParser.hpp +++ b/include/rfl/parsing/NamedTupleParser.hpp @@ -305,14 +305,16 @@ struct NamedTupleParser { set.fill(false); std::vector errors; const auto reader = ViewReaderType(&_r, _view, &found, &set, &errors); - std::optional err; if constexpr (_no_field_names) { - err = _r.read_array(reader, _obj_or_arr); + const auto err = _r.read_array(reader, _obj_or_arr); + if (err) { + return std::make_pair(set, err); + } } else { - err = _r.read_object(reader, _obj_or_arr); - } - if (err) { - return std::make_pair(set, err); + const auto err = _r.read_object(reader, _obj_or_arr); + if (err) { + return std::make_pair(set, err); + } } handle_missing_fields(found, *_view, &set, &errors, std::make_integer_sequence()); @@ -327,14 +329,16 @@ struct NamedTupleParser { NamedTupleType* _view) noexcept { std::vector errors; const auto reader = ViewReaderWithDefaultType(&_r, _view, &errors); - std::optional err; if constexpr (_no_field_names) { - err = _r.read_array(reader, _obj_or_arr); + const auto err = _r.read_array(reader, _obj_or_arr); + if (err) { + return err; + } } else { - err = _r.read_object(reader, _obj_or_arr); - } - if (err) { - return err; + const auto err = _r.read_object(reader, _obj_or_arr); + if (err) { + return err; + } } if (errors.size() != 0) { return to_single_error_message(errors);