Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: use concepts more #5537

Merged
merged 3 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/assign.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "json.h"
#include "units.h"
#include "units_serde.h"
#include "concepts_utility.h"

namespace detail
{
Expand All @@ -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 <typename T, typename std::enable_if<std::is_arithmetic<T>::value, int>::type = 0>
template <Arithmetic T>
bool assign( const JsonObject &jo, const std::string &name, T &val, bool strict = false,
T lo = std::numeric_limits<T>::lowest(), T hi = std::numeric_limits<T>::max() )
{
Expand Down Expand Up @@ -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 <typename T, typename std::enable_if<std::is_arithmetic<T>::value, int>::type = 0>
template <Arithmetic T>
bool assign( const JsonObject &jo, const std::string &name, std::pair<T, T> &val,
bool strict = false, T lo = std::numeric_limits<T>::lowest(), T hi = std::numeric_limits<T>::max() )
{
Expand Down
62 changes: 29 additions & 33 deletions src/generic_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -657,48 +657,45 @@ std::true_type {};
template<>
struct supports_proportional<bool> : std::false_type {};

template<typename T>
concept SupportsProportional = supports_proportional<T>::value;

// This checks that all units:: types will support relative and proportional
static_assert( supports_relative<units::energy>::value, "units should support relative" );
static_assert( supports_proportional<units::energy>::value, "units should support proportional" );
static_assert( SupportsRelative<units::energy>, "units should support relative" );
static_assert( SupportsProportional<units::energy>, "units should support proportional" );

static_assert( supports_relative<int>::value, "ints should support relative" );
static_assert( supports_proportional<int>::value, "ints should support proportional" );
static_assert( SupportsRelative<int>, "ints should support relative" );
static_assert( SupportsProportional<int>, "ints should support proportional" );

static_assert( !supports_relative<bool>::value, "bools should not support relative" );
static_assert( !supports_proportional<bool>::value, "bools should not support proportional" );
static_assert( !SupportsRelative<bool>, "bools should not support relative" );
static_assert( !SupportsProportional<bool>, "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<string_id<int>>::value,
"string ids should not support relative" );
static_assert( !supports_proportional<string_id<int>>::value,
static_assert( !SupportsRelative<string_id<int>>, "string ids should not support relative" );
static_assert( !SupportsProportional<string_id<int>>,
"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<int_id<int>>::value,
"int ids should not support relative" );
static_assert( !supports_proportional<int_id<int>>::value,
"int ids should not support proportional" );
static_assert( !SupportsRelative<int_id<int>>, "int ids should not support relative" );
static_assert( !SupportsProportional<int_id<int>>, "int ids should not support proportional" );

static_assert( !supports_relative<std::string>::value, "strings should not support relative" );
static_assert( !supports_proportional<std::string>::value,
"strings should not support proportional" );
static_assert( !SupportsRelative<std::string>, "strings should not support relative" );
static_assert( !SupportsProportional<std::string>, "strings should not support proportional" );

// Grab an enum class from debug.h
static_assert( !supports_relative<DebugOutput>::value, "enum classes should not support relative" );
static_assert( !supports_proportional<DebugOutput>::value,
"enum classes should not support proportional" );
static_assert( !SupportsRelative<DebugOutput>, "enum classes should not support relative" );
static_assert( !SupportsProportional<DebugOutput>, "enum classes should not support proportional" );

// Grab a normal enum from there too
static_assert( !supports_relative<DL>::value, "enums should not support relative" );
static_assert( !supports_proportional<DL>::value, "enums should not support relative" );
static_assert( !SupportsRelative<DL>, "enums should not support relative" );
static_assert( !SupportsProportional<DL>, "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<MemberType>::value > * =
nullptr >
template<typename MemberType> requires( !SupportsProportional<MemberType> )
inline bool handle_proportional( const JsonObject &jo, const std::string &name, MemberType & )
{
if( jo.has_object( "proportional" ) ) {
Expand All @@ -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<typename MemberType, std::enable_if_t<supports_proportional<MemberType>::value>* = nullptr>
template<SupportsProportional MemberType>
inline bool handle_proportional( const JsonObject &jo, const std::string &name, MemberType &member )
{
if( jo.has_object( "proportional" ) ) {
Expand Down Expand Up @@ -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<MemberType>::value > * = nullptr
>
template<typename MemberType> requires( !SupportsRelative<MemberType> )
inline bool handle_relative( const JsonObject &jo, const std::string &name, MemberType & )
{
if( jo.has_object( "relative" ) ) {
Expand All @@ -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<typename MemberType, std::enable_if_t<supports_relative<MemberType>::value>* = nullptr>
template<SupportsRelative MemberType>
inline bool handle_relative( const JsonObject &jo, const std::string &name, MemberType &member )
{
if( jo.has_object( "relative" ) ) {
Expand Down Expand Up @@ -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<typename MemberType, typename DefaultType = MemberType,
typename = typename std::enable_if<std::is_constructible<MemberType, const DefaultType &>::value>::type>
template<typename MemberType, typename DefaultType = MemberType>
requires( std::is_constructible_v<MemberType, const DefaultType &> )
inline void optional( const JsonObject &jo, const bool was_loaded, const std::string &name,
MemberType &member, const DefaultType &default_value )
{
Expand All @@ -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<MemberType, const ReaderType &>::value >::type >

template<typename MemberType, typename ReaderType, typename DefaultType = MemberType>
requires( !std::is_constructible_v<MemberType, const ReaderType &> )
inline void optional( const JsonObject &jo, const bool was_loaded, const std::string &name,
MemberType &member, const ReaderType &reader )
{
Expand All @@ -833,6 +828,7 @@ inline void optional( const JsonObject &jo, const bool was_loaded, const std::st
}
}
}

template<typename MemberType, typename ReaderType, typename DefaultType = MemberType>
inline void optional( const JsonObject &jo, const bool was_loaded, const std::string &name,
MemberType &member, const ReaderType &reader, const DefaultType &default_value )
Expand Down
17 changes: 9 additions & 8 deletions src/generic_readers.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,19 @@ struct supports_relative<bool> : std::false_type {};
template<>
struct supports_relative<std::string> : std::false_type {};

template<typename T> concept SupportsRelative = supports_relative<T>::value;

namespace reader_detail
{
template<typename T>
struct handler {
static constexpr bool is_container = false;
};

template<typename T> concept Container = handler<T>::is_container;

template<typename T> concept RelativeContainer = Container<T> &&SupportsRelative<T>;

template<typename T>
struct handler<std::set<T>> {
void clear( std::set<T> &container ) const {
Expand Down Expand Up @@ -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<C>::is_container,
int >::type = 0,
std::enable_if_t < !supports_relative<C>::value > * = nullptr
>
template<typename C> requires( !reader_detail::Container<C> || !SupportsRelative<C> )
bool do_relative( const JsonObject &jo, const std::string &name, C & ) const {
if( jo.has_object( "relative" ) ) {
JsonObject relative = jo.get_object( "relative" );
Expand All @@ -254,8 +257,7 @@ class generic_typed_reader
}

// Type supports relative
template < typename C, typename std::enable_if < !reader_detail::handler<C>::is_container,
int >::type = 0, std::enable_if_t<supports_relative<C>::value> * = nullptr >
template<reader_detail::RelativeContainer C>
bool do_relative( const JsonObject &jo, const std::string &name, C &member ) const {
if( jo.has_object( "relative" ) ) {
JsonObject relative = jo.get_object( "relative" );
Expand Down Expand Up @@ -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<C>::is_container,
int >::type = 0 >
template<typename C> requires( !reader_detail::Container<C> )
bool operator()( const JsonObject &jo, const std::string &member_name,
C &member, bool /*was_loaded*/ ) const {
return read_normal( jo, member_name, member ) ||
Expand Down
4 changes: 3 additions & 1 deletion src/numeric_interval.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
#include <limits>
#include <type_traits>

#include "concepts_utility.h"

/**
* An interval of numeric values between @ref min and @ref max (including both).
* By default it's [0, 0].
*/
template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
template<Arithmetic T>
struct numeric_interval {
T min = static_cast<T>( 0 );
T max = static_cast<T>( 0 );
Expand Down
Loading