Skip to content

Commit 80435ed

Browse files
committed
Replace std::enable_if with concept constraints
1 parent 6c2a161 commit 80435ed

File tree

1 file changed

+70
-56
lines changed

1 file changed

+70
-56
lines changed

include/graphqlservice/GraphQLService.h

Lines changed: 70 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,18 @@ enum class [[nodiscard]] TypeModifier {
592592
List,
593593
};
594594

595+
// Test if there are any non-None modifiers left.
596+
template <TypeModifier... Other>
597+
concept OnlyNoneModifiers = (... && (Other == TypeModifier::None));
598+
599+
// Test if the next modifier is Nullable.
600+
template <TypeModifier Modifier>
601+
concept NullableModifier = Modifier == TypeModifier::Nullable;
602+
603+
// Test if the next modifier is List.
604+
template <TypeModifier Modifier>
605+
concept ListModifier = Modifier == TypeModifier::List;
606+
595607
// These types are used as scalar arguments even though they are represented with a class.
596608
template <typename Type>
597609
concept ScalarArgumentClass = std::is_same_v<Type, std::string> || std::is_same_v<Type,
@@ -601,10 +613,6 @@ concept ScalarArgumentClass = std::is_same_v<Type, std::string> || std::is_same_
601613
template <typename Type>
602614
concept InputArgumentClass = std::is_class_v<Type> && !ScalarArgumentClass<Type>;
603615

604-
// Test if there are any non-None modifiers left.
605-
template <TypeModifier... Other>
606-
concept OnlyNoneModifiers = (... && (Other == TypeModifier::None));
607-
608616
// Special-case an innermost nullable INPUT_OBJECT type.
609617
template <typename Type, TypeModifier... Other>
610618
concept InputArgumentUniquePtr = InputArgumentClass<Type> && OnlyNoneModifiers<Other...>;
@@ -678,9 +686,8 @@ struct ModifiedArgument
678686

679687
// Peel off the none modifier. If it's included, it should always be last in the list.
680688
template <TypeModifier Modifier = TypeModifier::None, TypeModifier... Other>
681-
[[nodiscard]] static inline typename std::enable_if_t<TypeModifier::None == Modifier, Type>
682-
require(
683-
std::string_view name, const response::Value& arguments)
689+
[[nodiscard]] static inline Type require(std::string_view name,
690+
const response::Value& arguments) requires OnlyNoneModifiers<Modifier, Other...>
684691
{
685692
static_assert(sizeof...(Other) == 0, "None modifier should always be last");
686693

@@ -690,9 +697,8 @@ struct ModifiedArgument
690697

691698
// Peel off nullable modifiers.
692699
template <TypeModifier Modifier, TypeModifier... Other>
693-
[[nodiscard]] static inline typename std::enable_if_t<TypeModifier::Nullable == Modifier,
694-
typename ArgumentTraits<Type, Modifier, Other...>::type>
695-
require(std::string_view name, const response::Value& arguments)
700+
[[nodiscard]] static inline typename ArgumentTraits<Type, Modifier, Other...>::type require(
701+
std::string_view name, const response::Value& arguments) requires NullableModifier<Modifier>
696702
{
697703
const auto& valueItr = arguments.find(name);
698704

@@ -716,9 +722,8 @@ struct ModifiedArgument
716722

717723
// Peel off list modifiers.
718724
template <TypeModifier Modifier, TypeModifier... Other>
719-
[[nodiscard]] static inline typename std::enable_if_t<TypeModifier::List == Modifier,
720-
typename ArgumentTraits<Type, Modifier, Other...>::type>
721-
require(std::string_view name, const response::Value& arguments)
725+
[[nodiscard]] static inline typename ArgumentTraits<Type, Modifier, Other...>::type require(
726+
std::string_view name, const response::Value& arguments) requires ListModifier<Modifier>
722727
{
723728
const auto& values = arguments[name];
724729
typename ArgumentTraits<Type, Modifier, Other...>::type result(values.size());
@@ -756,19 +761,18 @@ struct ModifiedArgument
756761

757762
// Peel off the none modifier. If it's included, it should always be last in the list.
758763
template <TypeModifier Modifier = TypeModifier::None, TypeModifier... Other>
759-
[[nodiscard]] static inline
760-
typename std::enable_if_t<TypeModifier::None == Modifier && sizeof...(Other) == 0, Type>
761-
duplicate(const Type& value)
764+
[[nodiscard]] static inline Type duplicate(
765+
const Type& value) requires OnlyNoneModifiers<Modifier, Other...>
762766
{
763767
// Just copy the value.
764768
return Type { value };
765769
}
766770

767771
// Peel off nullable modifiers.
768772
template <TypeModifier Modifier, TypeModifier... Other>
769-
[[nodiscard]] static inline typename std::enable_if_t<TypeModifier::Nullable == Modifier,
770-
typename ArgumentTraits<Type, Modifier, Other...>::type>
771-
duplicate(const typename ArgumentTraits<Type, Modifier, Other...>::type& nullableValue)
773+
[[nodiscard]] static inline typename ArgumentTraits<Type, Modifier, Other...>::type duplicate(
774+
const typename ArgumentTraits<Type, Modifier, Other...>::type& nullableValue) requires
775+
NullableModifier<Modifier>
772776
{
773777
typename ArgumentTraits<Type, Modifier, Other...>::type result {};
774778

@@ -790,9 +794,9 @@ struct ModifiedArgument
790794

791795
// Peel off list modifiers.
792796
template <TypeModifier Modifier, TypeModifier... Other>
793-
[[nodiscard]] static inline typename std::enable_if_t<TypeModifier::List == Modifier,
794-
typename ArgumentTraits<Type, Modifier, Other...>::type>
795-
duplicate(const typename ArgumentTraits<Type, Modifier, Other...>::type& listValue)
797+
[[nodiscard]] static inline typename ArgumentTraits<Type, Modifier, Other...>::type duplicate(
798+
const typename ArgumentTraits<Type, Modifier, Other...>::type& listValue) requires
799+
ListModifier<Modifier>
796800
{
797801
typename ArgumentTraits<Type, Modifier, Other...>::type result(listValue.size());
798802

@@ -868,6 +872,22 @@ class [[nodiscard]] Object : public std::enable_shared_from_this<Object>
868872
ResolverMap _resolvers;
869873
};
870874

875+
// Test if this Type is Object.
876+
template <typename Type>
877+
concept ObjectType = std::is_same_v<Object, Type>;
878+
879+
// Test if this Type inherits from Object.
880+
template <typename Type>
881+
concept ObjectBaseType = std::is_base_of_v<Object, Type>;
882+
883+
// Test if this Type inherits from Object but is not Object itself.
884+
template <typename Type>
885+
concept ObjectDerivedType = ObjectBaseType<Type> && !ObjectType<Type>;
886+
887+
// Test if ResultType is std::shared_ptr<Type>.
888+
template <typename ResultType, typename Type>
889+
concept ResultTypeSharedPtr = std::is_same_v<ResultType, std::shared_ptr<Type>>;
890+
871891
// Convert the result of a resolver function with chained type modifiers that add nullable or
872892
// list wrappers. This is the inverse of ModifiedArgument for output types instead of input types.
873893
template <typename Type>
@@ -879,12 +899,12 @@ struct ModifiedResult
879899
{
880900
using type = typename std::conditional_t<TypeModifier::Nullable == Modifier,
881901
typename std::conditional_t<
882-
std::is_base_of_v<Object,
902+
ObjectBaseType<
883903
U> && std::is_same_v<std::shared_ptr<U>, typename ResultTraits<U, Other...>::type>,
884904
std::shared_ptr<U>, std::optional<typename ResultTraits<U, Other...>::type>>,
885905
typename std::conditional_t<TypeModifier::List == Modifier,
886906
std::vector<typename ResultTraits<U, Other...>::type>,
887-
typename std::conditional_t<std::is_base_of_v<Object, U>, std::shared_ptr<U>, U>>>;
907+
typename std::conditional_t<ObjectBaseType<U>, std::shared_ptr<U>, U>>>;
888908

889909
using future_type = typename std::conditional_t<std::is_base_of_v<Object, U>,
890910
AwaitableObject<type>, AwaitableScalar<type>>;
@@ -893,10 +913,9 @@ struct ModifiedResult
893913
template <typename U>
894914
struct ResultTraits<U, TypeModifier::None>
895915
{
896-
using type =
897-
typename std::conditional_t<std::is_base_of_v<Object, U>, std::shared_ptr<U>, U>;
916+
using type = typename std::conditional_t<ObjectBaseType<U>, std::shared_ptr<U>, U>;
898917

899-
using future_type = typename std::conditional_t<std::is_base_of_v<Object, U>,
918+
using future_type = typename std::conditional_t<ObjectBaseType<U>,
900919
AwaitableObject<std::shared_ptr<const Object>>, AwaitableScalar<type>>;
901920
};
902921

@@ -906,10 +925,9 @@ struct ModifiedResult
906925

907926
// Peel off the none modifier. If it's included, it should always be last in the list.
908927
template <TypeModifier Modifier = TypeModifier::None, TypeModifier... Other>
909-
[[nodiscard]] static inline typename std::enable_if_t<TypeModifier::None == Modifier
910-
&& !std::is_same_v<Object, Type> && std::is_base_of_v<Object, Type>,
911-
AwaitableResolver>
912-
convert(AwaitableObject<typename ResultTraits<Type>::type> result, ResolverParams params)
928+
[[nodiscard]] static inline AwaitableResolver convert(
929+
AwaitableObject<typename ResultTraits<Type>::type> result, ResolverParams params) requires
930+
OnlyNoneModifiers<Modifier, Other...> && ObjectDerivedType<Type>
913931
{
914932
// Call through to the Object specialization with a static_pointer_cast for subclasses of
915933
// Object.
@@ -928,10 +946,9 @@ struct ModifiedResult
928946

929947
// Peel off the none modifier. If it's included, it should always be last in the list.
930948
template <TypeModifier Modifier = TypeModifier::None, TypeModifier... Other>
931-
[[nodiscard]] static inline typename std::enable_if_t<TypeModifier::None == Modifier
932-
&& (std::is_same_v<Object, Type> || !std::is_base_of_v<Object, Type>),
933-
AwaitableResolver>
934-
convert(typename ResultTraits<Type>::future_type result, ResolverParams params)
949+
[[nodiscard]] static inline AwaitableResolver convert(
950+
typename ResultTraits<Type>::future_type result, ResolverParams params) requires
951+
OnlyNoneModifiers<Modifier, Other...> && !ObjectDerivedType<Type>
935952
{
936953
static_assert(sizeof...(Other) == 0, "None modifier should always be last");
937954

@@ -941,11 +958,11 @@ struct ModifiedResult
941958

942959
// Peel off final nullable modifiers for std::shared_ptr of Object and subclasses of Object.
943960
template <TypeModifier Modifier, TypeModifier... Other>
944-
[[nodiscard]] static inline typename std::enable_if_t<TypeModifier::Nullable == Modifier
945-
&& std::is_same_v<std::shared_ptr<Type>, typename ResultTraits<Type, Other...>::type>,
946-
AwaitableResolver>
947-
convert(
948-
typename ResultTraits<Type, Modifier, Other...>::future_type result, ResolverParams params)
961+
[[nodiscard]] static inline AwaitableResolver convert(
962+
typename ResultTraits<Type, Modifier, Other...>::future_type result,
963+
ResolverParams params) requires
964+
NullableModifier<Modifier> && ResultTypeSharedPtr<
965+
typename ResultTraits<Type, Other...>::type, Type>
949966
{
950967
co_await params.launch;
951968

@@ -964,11 +981,11 @@ struct ModifiedResult
964981

965982
// Peel off nullable modifiers for anything else, which should all be std::optional.
966983
template <TypeModifier Modifier, TypeModifier... Other>
967-
[[nodiscard]] static inline typename std::enable_if_t<TypeModifier::Nullable == Modifier
968-
&& !std::is_same_v<std::shared_ptr<Type>, typename ResultTraits<Type, Other...>::type>,
969-
AwaitableResolver>
970-
convert(
971-
typename ResultTraits<Type, Modifier, Other...>::future_type result, ResolverParams params)
984+
[[nodiscard]] static inline AwaitableResolver convert(
985+
typename ResultTraits<Type, Modifier, Other...>::future_type result,
986+
ResolverParams params) requires
987+
NullableModifier<Modifier> && !ResultTypeSharedPtr<
988+
typename ResultTraits<Type, Other...>::type, Type>
972989
{
973990
static_assert(std::is_same_v<std::optional<typename ResultTraits<Type, Other...>::type>,
974991
typename ResultTraits<Type, Modifier, Other...>::type>,
@@ -1003,10 +1020,9 @@ struct ModifiedResult
10031020

10041021
// Peel off list modifiers.
10051022
template <TypeModifier Modifier, TypeModifier... Other>
1006-
[[nodiscard]] static inline
1007-
typename std::enable_if_t<TypeModifier::List == Modifier, AwaitableResolver>
1008-
convert(typename ResultTraits<Type, Modifier, Other...>::future_type result,
1009-
ResolverParams params)
1023+
[[nodiscard]] static inline AwaitableResolver convert(
1024+
typename ResultTraits<Type, Modifier, Other...>::future_type result,
1025+
ResolverParams params) requires ListModifier<Modifier>
10101026
{
10111027
if constexpr (!std::is_base_of_v<Object, Type>)
10121028
{
@@ -1111,7 +1127,7 @@ struct ModifiedResult
11111127
// Peel off the none modifier. If it's included, it should always be last in the list.
11121128
template <TypeModifier Modifier = TypeModifier::None, TypeModifier... Other>
11131129
static inline void validateScalar(
1114-
typename std::enable_if_t<TypeModifier::None == Modifier, const response::Value&> value)
1130+
const response::Value& value) requires OnlyNoneModifiers<Modifier, Other...>
11151131
{
11161132
static_assert(sizeof...(Other) == 0, "None modifier should always be last");
11171133

@@ -1121,8 +1137,7 @@ struct ModifiedResult
11211137

11221138
// Peel off nullable modifiers.
11231139
template <TypeModifier Modifier, TypeModifier... Other>
1124-
static inline void validateScalar(
1125-
typename std::enable_if_t<TypeModifier::Nullable == Modifier, const response::Value&> value)
1140+
static inline void validateScalar(const response::Value& value) requires NullableModifier<Modifier>
11261141
{
11271142
if (value.type() != response::Type::Null)
11281143
{
@@ -1132,8 +1147,7 @@ struct ModifiedResult
11321147

11331148
// Peel off list modifiers.
11341149
template <TypeModifier Modifier, TypeModifier... Other>
1135-
static inline void validateScalar(
1136-
typename std::enable_if_t<TypeModifier::List == Modifier, const response::Value&> value)
1150+
static inline void validateScalar(const response::Value& value) requires ListModifier<Modifier>
11371151
{
11381152
if (value.type() != response::Type::List)
11391153
{
@@ -1150,8 +1164,8 @@ struct ModifiedResult
11501164
std::function<response::Value(typename ResultTraits<Type>::type, const ResolverParams&)>;
11511165

11521166
[[nodiscard]] static inline AwaitableResolver resolve(
1153-
typename ResultTraits<Type>::future_type result,
1154-
ResolverParams params, ResolverCallback&& resolver)
1167+
typename ResultTraits<Type>::future_type result, ResolverParams params,
1168+
ResolverCallback&& resolver)
11551169
{
11561170
static_assert(!std::is_base_of_v<Object, Type>,
11571171
"ModfiedResult<Object> needs special handling");

0 commit comments

Comments
 (0)