diff --git a/include/rfl/Attribute.hpp b/include/rfl/Attribute.hpp index 4d8a39a7..1af50846 100644 --- a/include/rfl/Attribute.hpp +++ b/include/rfl/Attribute.hpp @@ -33,22 +33,21 @@ struct Attribute { template Attribute(Attribute&& _attr) : value_(_attr.get()) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Attribute(const U& _value) : value_(_value) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Attribute(U&& _value) noexcept : value_(std::forward(_value)) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Attribute(const Attribute& _attr) : value_(_attr.value()) {} /// Assigns the underlying object to its default value. - template , - bool>::type = true> + template + requires std::is_default_constructible_v Attribute(const Default&) : value_(Type()) {} ~Attribute() = default; @@ -75,17 +74,16 @@ struct Attribute { } /// Assigns the underlying object. - template , - bool>::type = true> + template + requires std::is_convertible_v auto& operator=(const U& _value) { value_ = _value; return *this; } /// Assigns the underlying object to its default value. - template , - bool>::type = true> + template + requires std::is_default_constructible_v auto& operator=(const Default&) { value_ = Type(); return *this; diff --git a/include/rfl/Binary.hpp b/include/rfl/Binary.hpp index 02aa0471..6c5550d4 100644 --- a/include/rfl/Binary.hpp +++ b/include/rfl/Binary.hpp @@ -13,7 +13,7 @@ namespace rfl { /// Used to define a field in the NamedTuple. template -requires std::is_unsigned_v + requires std::is_unsigned_v struct Binary { /// The underlying type. using Type = T; @@ -36,16 +36,16 @@ struct Binary { template Binary(Binary&& _other) : value_(_other.get()) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Binary(const U& _value) : value_(_value) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Binary(U&& _value) noexcept : value_(std::forward(_value)) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Binary(const Binary& _other) : value_(_other.value()) {} Binary(const std::string& _str) @@ -69,8 +69,8 @@ struct Binary { } /// Assigns the underlying object. - template , - bool>::type = true> + template + requires std::is_convertible_v auto& operator=(const U& _value) { value_ = _value; return *this; diff --git a/include/rfl/DefaultVal.hpp b/include/rfl/DefaultVal.hpp index be6a6812..db43ebe4 100644 --- a/include/rfl/DefaultVal.hpp +++ b/include/rfl/DefaultVal.hpp @@ -72,17 +72,16 @@ struct DefaultVal { } /// Assigns the underlying object. - template , - bool>::type = true> + template + requires std::is_convertible_v auto& operator=(const U& _value) { value_ = _value; return *this; } /// Assigns the underlying object to its default value. - template , - bool>::type = true> + template + requires std::is_default_constructible_v auto& operator=(const Default&) { value_ = Type(); return *this; diff --git a/include/rfl/Description.hpp b/include/rfl/Description.hpp index 46692b7d..cc33560e 100644 --- a/include/rfl/Description.hpp +++ b/include/rfl/Description.hpp @@ -42,23 +42,22 @@ struct Description { template Description(Description<_description, U>&& _field) : value_(_field.get()) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Description(const U& _value) : value_(_value) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Description(U&& _value) noexcept : value_(std::forward(_value)) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Description(const Description<_description, U>& _field) : value_(_field.value()) {} /// Assigns the underlying object to its default value. - template , - bool>::type = true> + template + requires std::is_default_constructible_v Description(const Default&) : value_(Type()) {} ~Description() = default; @@ -88,29 +87,26 @@ struct Description { } /// Assigns the underlying object. - template , - bool>::type = true> + template + requires std::is_convertible_v auto& operator=(const U& _value) { value_ = _value; return *this; } /// Assigns the underlying object to its default value. - template , - bool>::type = true> + template + requires std::is_default_constructible_v auto& operator=(const Default&) { value_ = Type(); return *this; } /// Assigns the underlying object. - Description& operator=( - const Description& _field) = default; + Description& operator=(const Description& _field) = default; /// Assigns the underlying object. - Description& operator=( - Description&& _field) = default; + Description& operator=(Description&& _field) = default; /// Assigns the underlying object. template diff --git a/include/rfl/Field.hpp b/include/rfl/Field.hpp index e33fab2b..2f436dad 100644 --- a/include/rfl/Field.hpp +++ b/include/rfl/Field.hpp @@ -36,22 +36,21 @@ struct Field { template Field(Field<_name, U>&& _field) : value_(_field.get()) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Field(const U& _value) : value_(_value) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Field(U&& _value) noexcept : value_(std::forward(_value)) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Field(const Field<_name, U>& _field) : value_(_field.value()) {} /// Assigns the underlying object to its default value. - template , - bool>::type = true> + template + requires std::is_default_constructible_v Field(const Default&) : value_(Type()) {} ~Field() = default; @@ -84,17 +83,16 @@ struct Field { } /// Assigns the underlying object. - template , - bool>::type = true> + template + requires std::is_convertible_v auto& operator=(const U& _value) { value_ = _value; return *this; } /// Assigns the underlying object to its default value. - template , - bool>::type = true> + template + requires std::is_default_constructible_v auto& operator=(const Default&) { value_ = Type(); return *this; diff --git a/include/rfl/Flatten.hpp b/include/rfl/Flatten.hpp index b7a7726f..579cb7eb 100644 --- a/include/rfl/Flatten.hpp +++ b/include/rfl/Flatten.hpp @@ -31,12 +31,12 @@ struct Flatten { template Flatten(Flatten&& _f) : value_(_f.get()) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Flatten(const U& _value) : value_(_value) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Flatten(U&& _value) : value_(_value) {} ~Flatten() = default; @@ -66,8 +66,8 @@ struct Flatten { } /// Assigns the underlying object. - template , - bool>::type = true> + template + requires std::is_convertible_v Flatten& operator=(const U& _value) { value_ = _value; return *this; diff --git a/include/rfl/Generic.hpp b/include/rfl/Generic.hpp index 32a23576..3b1f97a6 100644 --- a/include/rfl/Generic.hpp +++ b/include/rfl/Generic.hpp @@ -38,16 +38,14 @@ class RFL_API Generic { Generic(const ReflectionType& _value); - template , - bool>::type = true> + template + requires std::is_convertible_v Generic(const T& _value) { value_ = _value; } - template , - bool>::type = true> + template + requires std::is_convertible_v Generic(T&& _value) noexcept : value_(std::forward(_value)) {} ~Generic(); @@ -65,9 +63,8 @@ class RFL_API Generic { Generic& operator=(VariantType&& _value) noexcept; /// Assigns the underlying object. - template , - bool>::type = true> + template + requires std::is_convertible_v auto& operator=(const T& _value) { using Type = std::remove_cvref_t; if constexpr (std::is_same_v) { diff --git a/include/rfl/Hex.hpp b/include/rfl/Hex.hpp index 42811e17..678697f2 100644 --- a/include/rfl/Hex.hpp +++ b/include/rfl/Hex.hpp @@ -12,7 +12,7 @@ namespace rfl { /// Used to define a field in the NamedTuple. template -requires std::is_integral_v + requires std::is_integral_v struct Hex { /// The underlying type. using Type = T; @@ -33,16 +33,16 @@ struct Hex { template Hex(Hex&& _other) : value_(_other.get()) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Hex(const U& _value) : value_(_value) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Hex(U&& _value) noexcept : value_(std::forward(_value)) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Hex(const Hex& _other) : value_(_other.value()) {} Hex(const std::string& _str) { @@ -67,8 +67,8 @@ struct Hex { } /// Assigns the underlying object. - template , - bool>::type = true> + template + requires std::is_convertible_v auto& operator=(const U& _value) { value_ = _value; return *this; diff --git a/include/rfl/Oct.hpp b/include/rfl/Oct.hpp index b466df0e..cbe2467f 100644 --- a/include/rfl/Oct.hpp +++ b/include/rfl/Oct.hpp @@ -13,7 +13,7 @@ namespace rfl { /// Used to define a field in the NamedTuple. template -requires std::is_integral_v + requires std::is_integral_v struct Oct { /// The underlying type. using Type = T; @@ -34,16 +34,16 @@ struct Oct { template Oct(Oct&& _other) : value_(_other.get()) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Oct(const U& _value) : value_(_value) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Oct(U&& _value) noexcept : value_(std::forward(_value)) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Oct(const Oct& _other) : value_(_other.value()) {} Oct(const std::string& _str) { @@ -68,8 +68,8 @@ struct Oct { } /// Assigns the underlying object. - template , - bool>::type = true> + template + requires std::is_convertible_v auto& operator=(const U& _value) { value_ = _value; return *this; diff --git a/include/rfl/Rename.hpp b/include/rfl/Rename.hpp index 685c1e25..99adc62a 100644 --- a/include/rfl/Rename.hpp +++ b/include/rfl/Rename.hpp @@ -39,22 +39,21 @@ struct Rename { template Rename(Rename<_name, U>&& _field) : value_(_field.get()) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Rename(const U& _value) : value_(_value) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Rename(U&& _value) noexcept : value_(std::forward(_value)) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Rename(const Rename<_name, U>& _field) : value_(_field.value()) {} /// Assigns the underlying object to its default value. - template , - bool>::type = true> + template + requires std::is_default_constructible_v Rename(const Default&) : value_(Type()) {} ~Rename() = default; @@ -84,17 +83,16 @@ struct Rename { } /// Assigns the underlying object. - template , - bool>::type = true> + template + requires std::is_convertible_v auto& operator=(const U& _value) { value_ = _value; return *this; } /// Assigns the underlying object to its default value. - template , - bool>::type = true> + template + requires std::is_default_constructible_v auto& operator=(const Default&) { value_ = Type(); return *this; diff --git a/include/rfl/Result.hpp b/include/rfl/Result.hpp index 4621f2bb..0d65fc33 100644 --- a/include/rfl/Result.hpp +++ b/include/rfl/Result.hpp @@ -27,8 +27,9 @@ class Error { Error& operator=(Error&&) = default; /// Returns the error message, equivalent to .what() in std::exception. - const std::string& what() const & { return what_; } - /// Moves the error message out of Error object and leaves what_ in a moved from state + const std::string& what() const& { return what_; } + /// Moves the error message out of Error object and leaves what_ in a moved + /// from state std::string what() && { return std::move(what_); } private: @@ -108,16 +109,16 @@ class Result { copy_from_other(_other); } - template , - bool>::type = true> + template + requires std::is_convertible_v Result(Result&& _other) : success_(_other && true) { auto temp = std::forward >(_other).transform( [](U&& _u) { return T(std::forward(_u)); }); move_from_other(temp); } - template , - bool>::type = true> + template + requires std::is_convertible_v Result(const Result& _other) : success_(_other && true) { auto temp = _other.transform([](const U& _u) { return T(_u); }); move_from_other(temp); @@ -201,8 +202,8 @@ class Result { } /// Assigns the underlying object. - template , - bool>::type = true> + template + requires std::is_convertible_v auto& operator=(const Result& _other) { const auto to_t = [](const U& _u) -> T { return _u; }; t_or_err_ = _other.transform(to_t).t_or_err_; diff --git a/include/rfl/TaggedUnion.hpp b/include/rfl/TaggedUnion.hpp index 1fea1be8..8df7267e 100644 --- a/include/rfl/TaggedUnion.hpp +++ b/include/rfl/TaggedUnion.hpp @@ -28,14 +28,12 @@ struct TaggedUnion { TaggedUnion(TaggedUnion<_discriminator, Ts...>&& _tagged_union) noexcept = default; - template , - bool>::type = true> + template + requires std::is_convertible_v TaggedUnion(const T& _t) : variant_(_t) {} - template , - bool>::type = true> + template + requires std::is_convertible_v TaggedUnion(T&& _t) noexcept : variant_(std::forward(_t)) {} ~TaggedUnion() = default; @@ -53,18 +51,16 @@ struct TaggedUnion { } /// Assigns the underlying object. - template , - bool>::type = true> + template + requires std::is_convertible_v TaggedUnion<_discriminator, Ts...>& operator=(T&& _variant) { variant_ = std::forward(_variant); return *this; } /// Assigns the underlying object. - template , - bool>::type = true> + template + requires std::is_convertible_v TaggedUnion<_discriminator, Ts...>& operator=(const T& _variant) { variant_ = _variant; return *this; @@ -121,24 +117,18 @@ template using possible_tags_t = typename PossibleTags::Type; template -bool operator==( - const TaggedUnion<_discriminator, Ts...>& lhs, - const TaggedUnion<_discriminator, Ts...>& rhs - ) { - +bool operator==(const TaggedUnion<_discriminator, Ts...>& lhs, + const TaggedUnion<_discriminator, Ts...>& rhs) { return (lhs.variant().index() == rhs.variant().index()) && - lhs.variant().visit( - [&rhs](const auto& l) { - return rhs.variant().visit( - [&l](const auto& r) -> bool { - if constexpr (std::is_same_v, std::decay_t>) - return l == r; - else - return false; - } - ); - } - ); + lhs.variant().visit([&rhs](const auto& l) { + return rhs.variant().visit([&l](const auto& r) -> bool { + if constexpr (std::is_same_v, + std::decay_t>) + return l == r; + else + return false; + }); + }); } } // namespace rfl diff --git a/include/rfl/Validator.hpp b/include/rfl/Validator.hpp index f3a13294..cd7cd578 100644 --- a/include/rfl/Validator.hpp +++ b/include/rfl/Validator.hpp @@ -41,13 +41,13 @@ struct Validator { Validator(const T& _value) : value_(ValidationType::validate(_value).value()) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Validator(U&& _value) : value_(ValidationType::validate(T(std::forward(_value))).value()) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Validator(const U& _value) : value_(ValidationType::validate(T(_value)).value()) {} @@ -66,24 +66,22 @@ struct Validator { } /// Assigns the underlying object. - Validator& operator=(const Validator& _other) = - default; + Validator& operator=(const Validator& _other) = default; /// Assigns the underlying object. - Validator& operator=(Validator&& _other) noexcept = - default; + Validator& operator=(Validator&& _other) noexcept = default; /// Assigns the underlying object. - template , - bool>::type = true> + template + requires std::is_convertible_v auto& operator=(U&& _value) noexcept { value_ = ValidationType::validate(T(std::forward(_value))).value(); return *this; } /// Assigns the underlying object. - template , - bool>::type = true> + template + requires std::is_convertible_v auto& operator=(const U& _value) { value_ = ValidationType::validate(T(_value)).value(); return *this; diff --git a/include/rfl/Variant.hpp b/include/rfl/Variant.hpp index 09b45f24..855a0462 100644 --- a/include/rfl/Variant.hpp +++ b/include/rfl/Variant.hpp @@ -49,28 +49,22 @@ class Variant { move_from_type(FirstAlternative()); } - Variant(const Variant& _other) - : index_(IndexType()), data_(DataType()) { + Variant(const Variant& _other) : index_(IndexType()), data_(DataType()) { copy_from_other(_other); } - Variant(Variant&& _other) noexcept - : index_(IndexType()), data_(DataType()) { + Variant(Variant&& _other) noexcept : index_(IndexType()), data_(DataType()) { move_from_other(std::move(_other)); } - template (), - bool>::type = true> + template + requires internal::variant::is_alternative_type_v Variant(const T& _t) : index_(IndexType()), data_(DataType()) { copy_from_type(_t); } - template (), - bool>::type = true> + template + requires internal::variant::is_alternative_type_v Variant(T&& _t) noexcept : index_(IndexType()), data_(DataType()) { move_from_type(std::forward(_t)); } @@ -97,10 +91,8 @@ class Variant { constexpr int index() const noexcept { return index_; } /// Assigns the underlying object. - template (), - bool>::type = true> + template + requires internal::variant::is_alternative_type_v Variant& operator=(const T& _t) { auto temp = Variant(_t); destroy_if_necessary(); @@ -109,10 +101,8 @@ class Variant { } /// Assigns the underlying object. - template (), - bool>::type = true> + template + requires internal::variant::is_alternative_type_v Variant& operator=(T&& _t) noexcept { destroy_if_necessary(); move_from_type(std::forward(_t)); @@ -311,9 +301,9 @@ class Variant { template void do_visit_with_result(const F& _f, std::optional* _result, std::integer_sequence) { - const auto visit_one = [this](const F& _f, - std::optional* _result, - Index<_i>) { + const auto visit_one = [this]( + const F& _f, std::optional* _result, + Index<_i>) { if (!*_result && index_ == _i) { _result->emplace(_f(get_alternative<_i>())); } @@ -324,9 +314,9 @@ class Variant { template void do_visit_with_result(const F& _f, std::optional* _result, std::integer_sequence) const { - const auto visit_one = [this](const F& _f, - std::optional* _result, - Index<_i>) { + const auto visit_one = [this]( + const F& _f, std::optional* _result, + Index<_i>) { if (!*_result && index_ == _i) { _result->emplace(_f(get_alternative<_i>())); } @@ -337,8 +327,8 @@ class Variant { template void do_visit_with_reference(F& _f, ResultType** _result, std::integer_sequence) { - const auto visit_one = [this](const F& _f, ResultType** _result, - Index<_i>) { + const auto visit_one = [this]( + const F& _f, ResultType** _result, Index<_i>) { if (!*_result && index_ == _i) { *_result = &_f(get_alternative<_i>()); } @@ -349,8 +339,8 @@ class Variant { template void do_visit_with_reference(F& _f, ResultType** _result, std::integer_sequence) const { - const auto visit_one = [this](const F& _f, ResultType** _result, - Index<_i>) { + const auto visit_one = [this]( + const F& _f, ResultType** _result, Index<_i>) { if (!*_result && index_ == _i) { *_result = &_f(get_alternative<_i>()); } @@ -361,8 +351,8 @@ class Variant { template void do_visit_with_reference(const F& _f, ResultType** _result, std::integer_sequence) { - const auto visit_one = [this](const F& _f, ResultType** _result, - Index<_i>) { + const auto visit_one = [this]( + const F& _f, ResultType** _result, Index<_i>) { if (!*_result && index_ == _i) { *_result = &_f(get_alternative<_i>()); } @@ -373,8 +363,8 @@ class Variant { template void do_visit_with_reference(const F& _f, ResultType** _result, std::integer_sequence) const { - const auto visit_one = [this](const F& _f, ResultType** _result, - Index<_i>) { + const auto visit_one = [this]( + const F& _f, ResultType** _result, Index<_i>) { if (!*_result && index_ == _i) { *_result = &_f(get_alternative<_i>()); } diff --git a/include/rfl/flexbuf/Reader.hpp b/include/rfl/flexbuf/Reader.hpp index 539c338c..854f8e95 100644 --- a/include/rfl/flexbuf/Reader.hpp +++ b/include/rfl/flexbuf/Reader.hpp @@ -24,23 +24,9 @@ struct Reader { using InputObjectType = flexbuffers::Map; using InputVarType = flexbuffers::Reference; - template - struct has_from_flexbuf : std::false_type {}; - - template - struct has_from_flexbuf< - T, std::enable_if_t::value>> - : std::true_type {}; - - template - struct has_from_flexbuf< - T, std::enable_if_t, decltype(T::from_flexbuf), InputVarType>::value>> - : std::true_type {}; - template - static constexpr bool has_custom_constructor = has_from_flexbuf::value; + static constexpr bool has_custom_constructor = + (requires(InputVarType var) { T::from_flexbuf(var); }); rfl::Result get_field_from_array( const size_t _idx, const InputArrayType& _arr) const noexcept { diff --git a/include/rfl/internal/Skip.hpp b/include/rfl/internal/Skip.hpp index a97603d4..843a167b 100644 --- a/include/rfl/internal/Skip.hpp +++ b/include/rfl/internal/Skip.hpp @@ -41,24 +41,21 @@ class Skip { template Skip(Skip&& _other) : value_(_other.get()) {} - - template , - bool>::type = true> + template + requires std::is_convertible_v Skip(const U& _value) : value_(_value) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Skip(U&& _value) noexcept : value_(std::forward(_value)) {} - template , - bool>::type = true> + template + requires std::is_convertible_v Skip(const Skip& _skip) : value_(_skip.value()) {} /// Assigns the underlying object to its default value. - template , - bool>::type = true> + template + requires std::is_default_constructible_v Skip(const Default&) : value_(Type()) {} ~Skip() = default; @@ -88,17 +85,16 @@ class Skip { } /// Assigns the underlying object. - template , - bool>::type = true> + template + requires std::is_convertible_v auto& operator=(const U& _value) { value_ = _value; return *this; } /// Assigns the underlying object to its default value. - template , - bool>::type = true> + template + requires std::is_default_constructible_v auto& operator=(const Default&) { value_ = Type(); return *this; diff --git a/include/rfl/internal/has_to_class_method_v.hpp b/include/rfl/internal/has_to_class_method_v.hpp index 92857fb0..d80dc7ea 100644 --- a/include/rfl/internal/has_to_class_method_v.hpp +++ b/include/rfl/internal/has_to_class_method_v.hpp @@ -1,28 +1,15 @@ #ifndef RFL_INTERNAL_HASTOCLASSMETHODV_HPP_ #define RFL_INTERNAL_HASTOCLASSMETHODV_HPP_ -#include +#include -namespace rfl { -namespace internal { +namespace rfl::internal { -template -using to_class_method_t = decltype(std::declval().to_class()); +template +constexpr bool has_to_class_method_v = requires(T t) { + { t.to_class() }; +}; -template > -struct has_to_class_m : std::false_type {}; - -template -struct has_to_class_m>> - : std::true_type {}; - -/// Utility parameter for named tuple parsing, can be used by the -/// parsers to determine whether a class or struct has a method -/// called "to_class". -template -constexpr bool has_to_class_method_v = has_to_class_m::value; - -} // namespace internal -} // namespace rfl +} // namespace rfl::internal #endif diff --git a/include/rfl/internal/is_basic_type.hpp b/include/rfl/internal/is_basic_type.hpp index a5b4ad6d..1a377cac 100644 --- a/include/rfl/internal/is_basic_type.hpp +++ b/include/rfl/internal/is_basic_type.hpp @@ -4,8 +4,7 @@ #include #include -namespace rfl { -namespace internal { +namespace rfl::internal { template constexpr bool is_basic_type_v = @@ -14,7 +13,6 @@ constexpr bool is_basic_type_v = std::is_same, std::string>() || std::is_same, bool>(); -} // namespace internal -} // namespace rfl +} // namespace rfl::internal #endif diff --git a/include/rfl/internal/variant/is_alternative_type.hpp b/include/rfl/internal/variant/is_alternative_type.hpp index af8e9525..2342e211 100644 --- a/include/rfl/internal/variant/is_alternative_type.hpp +++ b/include/rfl/internal/variant/is_alternative_type.hpp @@ -14,6 +14,10 @@ static constexpr bool is_alternative_type() { -1; } +template +constexpr bool is_alternative_type_v = + is_alternative_type(); + } // namespace rfl::internal::variant #endif diff --git a/include/rfl/parsing/Parser.hpp b/include/rfl/parsing/Parser.hpp index 0f7ef390..3bd444b0 100644 --- a/include/rfl/parsing/Parser.hpp +++ b/include/rfl/parsing/Parser.hpp @@ -3,12 +3,14 @@ #include "Parser_array.hpp" #include "Parser_base.hpp" +#include "Parser_basic_type.hpp" #include "Parser_box.hpp" #include "Parser_bytestring.hpp" #include "Parser_c_array.hpp" #include "Parser_default.hpp" #include "Parser_default_val.hpp" #include "Parser_duration.hpp" +#include "Parser_enum.hpp" #include "Parser_filepath.hpp" #include "Parser_map_like.hpp" #include "Parser_named_tuple.hpp" diff --git a/include/rfl/parsing/Parser_basic_type.hpp b/include/rfl/parsing/Parser_basic_type.hpp new file mode 100644 index 00000000..38587aff --- /dev/null +++ b/include/rfl/parsing/Parser_basic_type.hpp @@ -0,0 +1,96 @@ +#ifndef RFL_PARSING_PARSER_BASIC_TYPE_HPP_ +#define RFL_PARSING_PARSER_BASIC_TYPE_HPP_ + +#include +#include + +#include "../Result.hpp" +#include "../always_false.hpp" +#include "../enums.hpp" +#include "../from_named_tuple.hpp" +#include "../internal/has_default_val_v.hpp" +#include "../internal/has_reflection_method_v.hpp" +#include "../internal/has_reflection_type_v.hpp" +#include "../internal/has_reflector.hpp" +#include "../internal/is_basic_type.hpp" +#include "../internal/is_description.hpp" +#include "../internal/is_literal.hpp" +#include "../internal/is_underlying_enums_v.hpp" +#include "../internal/is_validator.hpp" +#include "../internal/processed_t.hpp" +#include "../internal/ptr_cast.hpp" +#include "../internal/to_ptr_named_tuple.hpp" +#include "../thirdparty/enchantum/enchantum.hpp" +#include "../to_view.hpp" +#include "AreReaderAndWriter.hpp" +#include "Parent.hpp" +#include "Parser_base.hpp" +#include "call_destructors_where_necessary.hpp" +#include "is_tagged_union_wrapper.hpp" +#include "make_type_name.hpp" +#include "schema/Type.hpp" +#include "schemaful/IsSchemafulReader.hpp" +#include "schemaful/IsSchemafulWriter.hpp" + +namespace rfl::parsing { + +/// Default case - anything that cannot be explicitly matched. +template + requires internal::is_basic_type_v && AreReaderAndWriter +struct Parser { + public: + using InputVarType = typename R::InputVarType; + + using ParentType = Parent; + + /// Expresses the variables as type T. + static Result read(const R& _r, const InputVarType& _var) noexcept { + return _r.template to_basic_type>(_var); + } + + template + static void write(const W& _w, const T& _var, const P& _parent) { + ParentType::add_value(_w, _var, _parent); + } + + /// Generates a schema for the underlying type. + static schema::Type to_schema( + std::map* _definitions) { + using U = std::remove_cvref_t; + using Type = schema::Type; + if constexpr (std::is_same()) { + return Type{Type::Boolean{}}; + + } else if constexpr (std::is_same()) { + return Type{Type::Int32{}}; + + } else if constexpr (std::is_same()) { + return Type{Type::Int64{}}; + + } else if constexpr (std::is_same()) { + return Type{Type::UInt32{}}; + + } else if constexpr (std::is_same()) { + return Type{Type::UInt64{}}; + + } else if constexpr (std::is_integral()) { + return Type{Type::Integer{}}; + + } else if constexpr (std::is_same()) { + return Type{Type::Float{}}; + + } else if constexpr (std::is_floating_point_v) { + return Type{Type::Double{}}; + + } else if constexpr (std::is_same()) { + return Type{Type::String{}}; + + } else { + static_assert(rfl::always_false_v, "Unsupported type."); + } + } +}; + +} // namespace rfl::parsing + +#endif diff --git a/include/rfl/parsing/Parser_default.hpp b/include/rfl/parsing/Parser_default.hpp index ced5e8db..1114cdaa 100644 --- a/include/rfl/parsing/Parser_default.hpp +++ b/include/rfl/parsing/Parser_default.hpp @@ -79,29 +79,12 @@ struct Parser { return Parser::read(_r, _var) .and_then(wrap_in_t); - } else if constexpr (std::is_class_v && std::is_aggregate_v) { - if constexpr (ProcessorsType::default_if_missing_ || - internal::has_default_val_v) { - return read_struct_with_default(_r, _var); - } else { - return read_struct(_r, _var); - } - - } else if constexpr (std::is_enum_v) { - if constexpr (ProcessorsType::underlying_enums_ || - schemaful::IsSchemafulReader) { - static_assert(enchantum::ScopedEnum, - "The enum must be a scoped enum in order to retrieve " - "the underlying value."); - return _r.template to_basic_type>(_var) - .transform([](const auto _val) { return static_cast(_val); }); - } else { - return _r.template to_basic_type(_var).and_then( - rfl::string_to_enum); - } + } else if constexpr (ProcessorsType::default_if_missing_ || + internal::has_default_val_v) { + return read_struct_with_default(_r, _var); } else { - return _r.template to_basic_type>(_var); + return read_struct(_r, _var); } } } @@ -126,25 +109,12 @@ struct Parser { Parser::write(_w, r, _parent); } - } else if constexpr (std::is_class_v && std::is_aggregate_v) { + } else { const auto ptr_named_tuple = ProcessorsType::template process( internal::to_ptr_named_tuple(_var)); using PtrNamedTupleType = std::remove_cvref_t; Parser::write( _w, ptr_named_tuple, _parent); - - } else if constexpr (std::is_enum_v) { - if constexpr (ProcessorsType::underlying_enums_ || - schemaful::IsSchemafulWriter) { - const auto val = static_cast>(_var); - ParentType::add_value(_w, val, _parent); - } else { - const auto str = rfl::enum_to_string(_var); - ParentType::add_value(_w, str, _parent); - } - - } else { - ParentType::add_value(_w, _var, _parent); } } @@ -153,39 +123,10 @@ struct Parser { std::map* _definitions) { using U = std::remove_cvref_t; using Type = schema::Type; - if constexpr (std::is_same()) { - return Type{Type::Boolean{}}; - - } else if constexpr (std::is_same()) { - return Type{Type::Int32{}}; - - } else if constexpr (std::is_same()) { - return Type{Type::Int64{}}; - - } else if constexpr (std::is_same()) { - return Type{Type::UInt32{}}; - } else if constexpr (std::is_same()) { - return Type{Type::UInt64{}}; - - } else if constexpr (std::is_integral()) { - return Type{Type::Integer{}}; - - } else if constexpr (std::is_same()) { - return Type{Type::Float{}}; - - } else if constexpr (std::is_floating_point_v) { - return Type{Type::Double{}}; - - } else if constexpr (std::is_same()) { - return Type{Type::String{}}; - - } else if constexpr (rfl::internal::is_description_v) { + if constexpr (rfl::internal::is_description_v) { return make_description(_definitions); - } else if constexpr (std::is_enum_v) { - return make_enum(_definitions); - } else if constexpr (std::is_class_v && std::is_aggregate_v) { return make_reference(_definitions); @@ -217,23 +158,6 @@ struct Parser { ProcessorsType>::to_schema(_definitions))}}; } - template - static schema::Type make_enum( - std::map* _definitions) { - using Type = schema::Type; - if constexpr (ProcessorsType::underlying_enums_ || - schemaful::IsSchemafulReader) { - return Type{Type::Integer{}}; - } else if constexpr (enchantum::is_bitflag) { - return Type{Type::String{}}; - } else { - return Parser< - R, W, - typename decltype(internal::enums::get_enum_names())::Literal, - ProcessorsType>::to_schema(_definitions); - } - } - template static schema::Type make_reference( std::map* _definitions) { @@ -277,10 +201,10 @@ struct Parser { .validation_ = ValidationType::template to_schema()}}; } - /// The way this works is that we allocate space on the stack in this size of - /// the struct in which we then write the individual fields using - /// views and placement new. This is how we deal with the fact that some - /// fields might not be default-constructible. + /// The way this works is that we allocate space on the stack in this size + /// of the struct in which we then write the individual fields using views + /// and placement new. This is how we deal with the fact that some fields + /// might not be default-constructible. static Result read_struct(const R& _r, const InputVarType& _var) { alignas(T) unsigned char buf[sizeof(T)]{}; auto ptr = internal::ptr_cast(&buf); @@ -297,10 +221,10 @@ struct Parser { return res; } - /// This is actually more straight-forward than the standard case - we just - /// allocate a struct and then fill it. But it is less efficient and it - /// assumes that all values on the struct have a default constructor, so we - /// only use it when the DefaultIfMissing preprocessor is added. + /// This is actually more straight-forward than the standard case - we + /// just allocate a struct and then fill it. But it is less efficient and + /// it assumes that all values on the struct have a default constructor, + /// so we only use it when the DefaultIfMissing preprocessor is added. static Result read_struct_with_default(const R& _r, const InputVarType& _var) { auto t = T{}; diff --git a/include/rfl/parsing/Parser_enum.hpp b/include/rfl/parsing/Parser_enum.hpp new file mode 100644 index 00000000..283b94ba --- /dev/null +++ b/include/rfl/parsing/Parser_enum.hpp @@ -0,0 +1,84 @@ +#ifndef RFL_PARSING_PARSER_ENUM_HPP_ +#define RFL_PARSING_PARSER_ENUM_HPP_ + +#include +#include + +#include "../Result.hpp" +#include "../enums.hpp" +#include "../thirdparty/enchantum/enchantum.hpp" +#include "AreReaderAndWriter.hpp" +#include "Parent.hpp" +#include "Parser_base.hpp" +#include "call_destructors_where_necessary.hpp" +#include "make_type_name.hpp" +#include "schema/Type.hpp" +#include "schemaful/IsSchemafulReader.hpp" +#include "schemaful/IsSchemafulWriter.hpp" + +namespace rfl::parsing { + +/// Default case - anything that cannot be explicitly matched. +template + requires std::is_enum_v && AreReaderAndWriter +struct Parser { + public: + using InputVarType = typename R::InputVarType; + + using ParentType = Parent; + + /// Expresses the variables as type T. + static Result read(const R& _r, const InputVarType& _var) noexcept { + if constexpr (ProcessorsType::underlying_enums_ || + schemaful::IsSchemafulReader) { + static_assert(enchantum::ScopedEnum, + "The enum must be a scoped enum in order to retrieve " + "the underlying value."); + return _r.template to_basic_type>(_var) + .transform([](const auto _val) { return static_cast(_val); }); + } else { + return _r.template to_basic_type(_var).and_then( + rfl::string_to_enum); + } + } + + template + static void write(const W& _w, const T& _var, const P& _parent) { + if constexpr (ProcessorsType::underlying_enums_ || + schemaful::IsSchemafulWriter) { + const auto val = static_cast>(_var); + ParentType::add_value(_w, val, _parent); + } else { + const auto str = rfl::enum_to_string(_var); + ParentType::add_value(_w, str, _parent); + } + } + + static schema::Type to_schema( + std::map* _definitions) { + using U = std::remove_cvref_t; + return make_enum(_definitions); + } + + private: + template + static schema::Type make_enum( + std::map* _definitions) { + using Type = schema::Type; + if constexpr (ProcessorsType::underlying_enums_ || + schemaful::IsSchemafulReader) { + return Type{Type::Integer{}}; + } else if constexpr (enchantum::is_bitflag) { + return Type{Type::String{}}; + } else { + return Parser< + R, W, + typename decltype(internal::enums::get_enum_names())::Literal, + ProcessorsType>::to_schema(_definitions); + } + } +}; + +} // namespace rfl::parsing + +#endif