From 1510f8189f5121e9743c257b0588dbcc0941901c Mon Sep 17 00:00:00 2001 From: scarf Date: Wed, 9 Oct 2024 04:04:47 +0900 Subject: [PATCH] refactor: use concepts more (#5537) * refactor: use `Arithmetic` * refactor: use `SupportsProportional`, `SupportsRelative` * refactor: MemberType --- src/assign.h | 5 ++-- src/generic_factory.h | 62 ++++++++++++++++++++---------------------- src/generic_readers.h | 17 ++++++------ src/numeric_interval.h | 4 ++- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/assign.h b/src/assign.h index d69394b00b96..c4ba8e82e871 100644 --- a/src/assign.h +++ b/src/assign.h @@ -18,6 +18,7 @@ #include "json.h" #include "units.h" #include "units_serde.h" +#include "concepts_utility.h" namespace detail { @@ -43,7 +44,7 @@ bool is_strict_enabled( const std::string &src ); void report_strict_violation( const JsonObject &jo, const std::string &message, const std::string &name ); -template ::value, int>::type = 0> +template bool assign( const JsonObject &jo, const std::string &name, T &val, bool strict = false, T lo = std::numeric_limits::lowest(), T hi = std::numeric_limits::max() ) { @@ -95,7 +96,7 @@ bool assign( const JsonObject &jo, const std::string &name, T &val, bool strict // and also to avoid potentially nonsensical interactions between relative and proportional. bool assign( const JsonObject &jo, const std::string &name, bool &val, bool strict = false ); -template ::value, int>::type = 0> +template bool assign( const JsonObject &jo, const std::string &name, std::pair &val, bool strict = false, T lo = std::numeric_limits::lowest(), T hi = std::numeric_limits::max() ) { diff --git a/src/generic_factory.h b/src/generic_factory.h index 434245c62ada..6eff35cb6752 100644 --- a/src/generic_factory.h +++ b/src/generic_factory.h @@ -657,48 +657,45 @@ std::true_type {}; template<> struct supports_proportional : std::false_type {}; +template +concept SupportsProportional = supports_proportional::value; + // This checks that all units:: types will support relative and proportional -static_assert( supports_relative::value, "units should support relative" ); -static_assert( supports_proportional::value, "units should support proportional" ); +static_assert( SupportsRelative, "units should support relative" ); +static_assert( SupportsProportional, "units should support proportional" ); -static_assert( supports_relative::value, "ints should support relative" ); -static_assert( supports_proportional::value, "ints should support proportional" ); +static_assert( SupportsRelative, "ints should support relative" ); +static_assert( SupportsProportional, "ints should support proportional" ); -static_assert( !supports_relative::value, "bools should not support relative" ); -static_assert( !supports_proportional::value, "bools should not support proportional" ); +static_assert( !SupportsRelative, "bools should not support relative" ); +static_assert( !SupportsProportional, "bools should not support proportional" ); // Using string ids with ints doesn't make sense in practice, but it doesn't matter here // The type that it is templated with does not change it's behavior -static_assert( !supports_relative>::value, - "string ids should not support relative" ); -static_assert( !supports_proportional>::value, +static_assert( !SupportsRelative>, "string ids should not support relative" ); +static_assert( !SupportsProportional>, "string ids should not support proportional" ); // Using int ids with ints doesn't make sense in practice, but it doesn't matter here // The type that it is templated with does not change it's behavior -static_assert( !supports_relative>::value, - "int ids should not support relative" ); -static_assert( !supports_proportional>::value, - "int ids should not support proportional" ); +static_assert( !SupportsRelative>, "int ids should not support relative" ); +static_assert( !SupportsProportional>, "int ids should not support proportional" ); -static_assert( !supports_relative::value, "strings should not support relative" ); -static_assert( !supports_proportional::value, - "strings should not support proportional" ); +static_assert( !SupportsRelative, "strings should not support relative" ); +static_assert( !SupportsProportional, "strings should not support proportional" ); // Grab an enum class from debug.h -static_assert( !supports_relative::value, "enum classes should not support relative" ); -static_assert( !supports_proportional::value, - "enum classes should not support proportional" ); +static_assert( !SupportsRelative, "enum classes should not support relative" ); +static_assert( !SupportsProportional, "enum classes should not support proportional" ); // Grab a normal enum from there too -static_assert( !supports_relative
::value, "enums should not support relative" ); -static_assert( !supports_proportional
::value, "enums should not support relative" ); +static_assert( !SupportsRelative
, "enums should not support relative" ); +static_assert( !SupportsProportional
, "enums should not support relative" ); // Dummy template: // Warn if it's trying to use proportional where it cannot, but otherwise just // return. -template < typename MemberType, std::enable_if_t < !supports_proportional::value > * = - nullptr > +template requires( !SupportsProportional ) inline bool handle_proportional( const JsonObject &jo, const std::string &name, MemberType & ) { if( jo.has_object( "proportional" ) ) { @@ -717,7 +714,7 @@ inline bool handle_proportional( const JsonObject &jo, const std::string &name, // this, so member will contain the value of the thing we inherit from // So, check if there is a proportional entry, check if it's got a valid value // and if it does, multiply the member by it. -template::value>* = nullptr> +template inline bool handle_proportional( const JsonObject &jo, const std::string &name, MemberType &member ) { if( jo.has_object( "proportional" ) ) { @@ -745,9 +742,7 @@ inline bool handle_proportional( const JsonObject &jo, const std::string &name, // Dummy template: // Warn when trying to use relative when it's not supported, but otherwise, // return -template < typename MemberType, - std::enable_if_t < !supports_relative::value > * = nullptr - > +template requires( !SupportsRelative ) inline bool handle_relative( const JsonObject &jo, const std::string &name, MemberType & ) { if( jo.has_object( "relative" ) ) { @@ -766,7 +761,7 @@ inline bool handle_relative( const JsonObject &jo, const std::string &name, Memb // Copy-from makes it so the thing we're inheriting from is used to construct // this, so member will contain the value of the thing we inherit from // So, check if there is a relative entry, then add it to our member -template::value>* = nullptr> +template inline bool handle_relative( const JsonObject &jo, const std::string &name, MemberType &member ) { if( jo.has_object( "relative" ) ) { @@ -809,8 +804,8 @@ words: `MemberType foo( ReaderType(...) );` does not work. This is what `is_cons If the 5. parameter can be used to construct a `MemberType`, it is assumed to be the default value, otherwise it is assumed to be the reader. */ -template::value>::type> +template +requires( std::is_constructible_v ) inline void optional( const JsonObject &jo, const bool was_loaded, const std::string &name, MemberType &member, const DefaultType &default_value ) { @@ -821,9 +816,9 @@ inline void optional( const JsonObject &jo, const bool was_loaded, const std::st } } } -template < typename MemberType, typename ReaderType, typename DefaultType = MemberType, - typename = typename std::enable_if < - !std::is_constructible::value >::type > + +template +requires( !std::is_constructible_v ) inline void optional( const JsonObject &jo, const bool was_loaded, const std::string &name, MemberType &member, const ReaderType &reader ) { @@ -833,6 +828,7 @@ inline void optional( const JsonObject &jo, const bool was_loaded, const std::st } } } + template inline void optional( const JsonObject &jo, const bool was_loaded, const std::string &name, MemberType &member, const ReaderType &reader, const DefaultType &default_value ) diff --git a/src/generic_readers.h b/src/generic_readers.h index 4f5948fdc3b8..e7ac43a242e3 100644 --- a/src/generic_readers.h +++ b/src/generic_readers.h @@ -32,6 +32,8 @@ struct supports_relative : std::false_type {}; template<> struct supports_relative : std::false_type {}; +template concept SupportsRelative = supports_relative::value; + namespace reader_detail { template @@ -39,6 +41,10 @@ struct handler { static constexpr bool is_container = false; }; +template concept Container = handler::is_container; + +template concept RelativeContainer = Container &&SupportsRelative; + template struct handler> { void clear( std::set &container ) const { @@ -237,10 +243,7 @@ class generic_typed_reader * whereas these are reading values of the same type. */ // Type does not support relative - template < typename C, typename std::enable_if < !reader_detail::handler::is_container, - int >::type = 0, - std::enable_if_t < !supports_relative::value > * = nullptr - > + template requires( !reader_detail::Container || !SupportsRelative ) bool do_relative( const JsonObject &jo, const std::string &name, C & ) const { if( jo.has_object( "relative" ) ) { JsonObject relative = jo.get_object( "relative" ); @@ -254,8 +257,7 @@ class generic_typed_reader } // Type supports relative - template < typename C, typename std::enable_if < !reader_detail::handler::is_container, - int >::type = 0, std::enable_if_t::value> * = nullptr > + template bool do_relative( const JsonObject &jo, const std::string &name, C &member ) const { if( jo.has_object( "relative" ) ) { JsonObject relative = jo.get_object( "relative" ); @@ -287,8 +289,7 @@ class generic_typed_reader */ // was_loaded is ignored here, if the value is not found in JSON, report to // the caller, which will take action on their own. - template < typename C, typename std::enable_if < !reader_detail::handler::is_container, - int >::type = 0 > + template requires( !reader_detail::Container ) bool operator()( const JsonObject &jo, const std::string &member_name, C &member, bool /*was_loaded*/ ) const { return read_normal( jo, member_name, member ) || diff --git a/src/numeric_interval.h b/src/numeric_interval.h index a7e463b2d064..a89b6a69f20e 100644 --- a/src/numeric_interval.h +++ b/src/numeric_interval.h @@ -5,11 +5,13 @@ #include #include +#include "concepts_utility.h" + /** * An interval of numeric values between @ref min and @ref max (including both). * By default it's [0, 0]. */ -template::value, T>::type> +template struct numeric_interval { T min = static_cast( 0 ); T max = static_cast( 0 );