hyperion::mpl::Pair#
- group pair
Hyperion provides
mpl::Pair
as a metaprogramming type for storing, communicating, working with, and operating on pairs of types or values.Example#
#include <hyperion/mpl/pair.h> using namespace hyperion::mpl; constexpr auto add_const = [](MetaPair auto pair) noexcept { return make_pair(pair.make_first().as_const(), pair.make_second().as_const()); }; constexpr auto pair = Pair<int, double>{}; constexpr auto constified = pair.apply(add_const); static_assert(constified == Pair<const int, const double>{});
Functions
-
template<typename TLHSFirst, typename TLHSSecond, typename TRHSFirst, typename TRHSSecond>
constexpr auto operator==(const Pair<TLHSFirst, TLHSSecond> &lhs, const Pair<TRHSFirst, TRHSSecond> &rhs) noexcept -> bool# Equality comparison operator between two
Pair
specializations.Checks that
lhs
andrhs
both represent the same metaprogramming types and values.Example#
constexpr auto first = Pair<int, Value<1, std::uint32_t>>{}; constexpr auto second = Pair<int, Value<1, std::uint64_t>>{}; static_assert(first == second);
- Template Parameters:
- Parameters:
- Returns:
whether
lhs
represents the same metaprogramming types and values asrhs
-
template<typename TFirst, typename TSecond>
constexpr auto make_pair(TFirst &&first, TSecond &&second) noexcept -> Pair<detail::convert_to_raw_t<TFirst>, detail::convert_to_raw_t<TSecond>># Constructs an
mpl::Pair
representing the types of the given arguments.If
TFirst
orTSecond
are metaprogramming types, first converts them to their raw type before storing in thePair
. (e.g. if either arempl::Type<some_type>
, the returned pair would bePair<some_type1, some_type2>
, notPair<Type<some_type1>, Type<some_type2>>
).This overload does not accept reference qualified parameters.
Requirements#
TFirst
is not reference qualifiedTSecond
is not reference qualified
Example#
constexpr auto pair = make_pair(decltype_<int>(), decltype_<double>()); static_assert(pair == Pair<int, double>{});
-
template<typename TFirst, typename TSecond>
struct Pair# - #include <hyperion/mpl/pair.h>
Pair
is Hyperion’s metaprogramming type for operating on pairs of types or values.Example#
#include <hyperion/mpl/pair.h> using namespace hyperion::mpl; constexpr auto add_const = [](MetaPair auto pair) noexcept { return make_pair(pair.make_first().as_const(), pair.make_second().as_const()); }; constexpr auto pair = Pair<int, double>{}; constexpr auto constified = pair.apply(add_const); static_assert(constified == Pair<const int, const double>{});
- Template Parameters:
TFirst – The first type to store in the pair
TSecond – The second type to store in the pair
Public Types
Public Functions
-
template<typename TDelay = first>
inline constexpr auto make_first() const noexcept -> TDelay# Returns an instance of
first
Example#
constexpr auto first = Pair<int, double>{}.make_first(); static_assert(first == decltype_<int>());
- Returns:
an instance of
first
-
template<typename TDelay = second>
inline constexpr auto make_second() const noexcept -> TDelay# Returns an instance of
second
Example#
constexpr auto second = Pair<int, double>{}.make_second(); static_assert(second == decltype_<double>());
- Returns:
an instance of
second
-
template<template<typename> typename TMetaFunction>
inline constexpr auto apply() const noexcept -> detail::convert_to_meta_t<TMetaFunction<Pair>># Applies the template metafunction
TMetaFunction
to thisPair
.Applies
TMetaFunction
to thisPair
, and returns the result as a metaprogramming type (a specialization ofmpl::Type
,mpl::Value
, ormpl::Pair
).Requirements#
Example#
template<typename TType> requires (!MetaPair<TType>) struct add_one_or_const { using type = std::conditional_t<MetaValue<TType>, decltype(TType{} + 1_value), decltype(decltype_<TType>().as_const())>; }; template<typename TPair> struct add_one_or_const_to_pair { using first = typename add_one_or_const<typename TPair::first>::type; using second = typename add_one_or_const<typename TPair::second>::type; }; static_assert(Pair<int, Value<1>>{}.apply<add_one_or_const_to_pair>() == Pair<const int, Value<2>>{});
- Template Parameters:
TMetaFunction – The template metafunction to apply
- Returns:
The result of applying
TMetaFunction
to thisPair
, as a metaprogramming type
-
template<template<typename> typename TMetaFunction>
inline constexpr auto apply() const noexcept# Applies the template metafunction
TMetaFunction
to the types represented in thisPair
.Applies
TMetaFunction
tofirst
andsecond
individually, returning the results together as a specialization ofPair
. AppliesTMetaFunction
to each offirst
andsecond
as if bymake().template apply<TMetaFunction>()
, wheremake
ismake_first
ormake_second
, respectively.Requirements#
TMetaFunction
must not be instantiatable with this specialization ofPair
. I.E.TMetaFunction<Pair>
must not be well-formed (this is most easily achievable by adding a requirement clause ofrequires (!MetaPair<TType>)
to yourTMetaFunction
, whereTType
is the type parameter of the template).TMetaFunction
must be applicable to bothfirst
andsecond
. I.E.,make().template apply<TMetaFunction>()
, wheremake
ismake_first
ormake_second
, respectively, must be well formed.
Example#
template<typename TType> requires (!MetaPair<TType>) struct add_one_or_const { using type = std::conditional_t<MetaValue<TType>, decltype(TType{} + 1_value), decltype(decltype_<TType>().as_const())>; }; static_assert(Pair<int, Value<1>>{}.apply<add_one_or_const>() == Pair<const int, Value<2>>{});
- Template Parameters:
TMetaFunction – The template metafunction to apply
- Returns:
The result of applying
TMetaFunction
to thisPair
, as a metaprogramming type
-
template<typename TFunction>
inline constexpr auto apply(TFunction &&func) const noexcept -> meta_result_t<TFunction, Pair># Applies the metafunction
TFunction
to thisPair
.Applies
TFunction
to thisPair
, as if bystd::forward<TFunction>(func)(Pair{})
, and returns the resulting metaprogramming type.Requirements#
TFunction
must be aMetaFunctionOf<Pair>
.
Example#
constexpr auto add_one_or_const = [](MetaPair auto pair) noexcept { constexpr auto apply_to_inner = [](auto inner) noexcept { if constexpr(MetaType<decltype(inner)>) { return inner.as_const(); } else if constexpr(MetaValue<decltype(inner)>) { return inner + 1_value; } }; return make_pair(pair.make_first().apply(apply_to_inner), pair.make_second().apply(apply_to_inner)); }; static_assert(Pair<int, Value<1>>{}.apply(add_one_or_const) == Pair<const int, Value<2>>{});
- Template Parameters:
TFunction – The type of the metafunction to apply
- Parameters:
func – The metafunction to apply
- Returns:
The result of applying
TFunction
to thisPair
-
template<typename TFunction>
inline constexpr auto apply(TFunction &&func) const noexcept -> Pair<meta_result_t<TFunction, first>, meta_result_t<TFunction, second>># Applies the metafunction
TFunction
to the types represented in thisPair
.Applies
TFunction
tofirst
andsecond
individually, returning the results together as a specialization ofPair
. AppliesTFunction
to each offirst
andsecond
as if bymake().apply(std::forward<TFunction>(func))
, wheremake
ismake_first
ormake_second
, respectively.Requirements#
TFunction
must be aMetaFunctionOf<first>
.TFunction
must be aMetaFunctionOf<second>
.TFunction
must not be aMetaFunctionOf<Pair>
.
Example#
constexpr auto add_one_or_const = [](auto val) noexcept requires (!MetaPair<decltype(val)>) { if constexpr(MetaType<decltype(val)>) { return val.as_const(); } else if constexpr(MetaValue<decltype(val)>) { return val + 1_value; } }; static_assert(Pair<int, Value<1>>{}.apply(add_one_or_const) == Pair<const int, Value<2>>{});
- Template Parameters:
TFunction – The type of the metafunction to apply
- Parameters:
func – The metafunction to apply
- Returns:
The result of applying
TFunction
to the types represented in thisPair
-
template<template<typename> typename TPredicate>
inline constexpr auto satisfies() const noexcept -> detail::convert_to_meta_t<TPredicate<Pair>># Checks that this
Pair
satisfies the template metafunction predicate,TPredicate
.Checks that this
Pair
satisfiesTPredicate
and returns the result as anmpl:Value<result, bool>
.Requirements#
TPredicate
must be instantiatable with this specialization ofPair
(i.e.TPredicate<Pair>
must be well-formed).The specialization of
TMetaFunction
forPair
,TMetaFunction<Pair>
, must be aMetaValue
The value of the specialization of
TMetaFunction
forPair
,TMetaFunction<Pair>::value
, must be of type (possibly cv-ref qualified)bool
Example#
template<typename TType> requires (!MetaPair<TType>) struct is_one_or_const { static inline constexpr auto value = false; }; template<typename TType> requires MetaValue<TType> struct is_one_or_const<TType> { static inline constexpr auto value = TType::value == 1; }; template<typename TType> requires MetaType<TType> struct is_one_or_const<TType> { static inline constexpr auto value = std::is_const_v<typename TType::type>; }; template<typename TPair> struct is_one_or_const_in_pair { static inline constexpr auto value = is_one_or_const<typename TPair::first>::value && is_one_or_const<typename TPair::second>::value; }; static_assert(Pair<int, Value<1>>{}.satisfies<is_one_or_const_in_pair>());
- Template Parameters:
TPredicate – The template metafunction predicate to validate
- Returns:
whether this
Pair
satisfiesTPredicate
, as anmpl::Value
-
template<template<typename> typename TPredicate>
inline constexpr auto satisfies() const noexcept# Checks that the types represented by this
Pair
satisfy the template metafunction predicate,TPredicate
.Checks that
first
andsecond
both satisfyTPredicate
, and returns the result as anmpl:Value<result, bool>
. Checks thatfirst
andsecond
both satisfyTPredicate
as if bymake().template satisfies<TPredicate>()
wheremake
ismake_first
ormake_second
, respectively.Requirements#
TPredicate
must not be instantiatable with this specialization ofPair
. I.E.,TPredicate<Pair>
must not be well-formed (this is most easily achievable by adding a requirement clause ofrequires (!MetaPair<TType>)
to yourTPredicate
, whereTType
is the type parameter of the template).TPredicate
must be a template metafunction predicate capable of being satisfied by bothfirst
andsecond
. I.E.,TMetaFunction<first>
andTMetaFunction<second>
must be well-formed.
Example#
template<typename TType> requires (!MetaPair<TType>) struct is_one_or_const { static inline constexpr auto value = false; }; template<typename TType> requires MetaValue<TType> struct is_one_or_const<TType> { static inline constexpr auto value = TType::value == 1; }; template<typename TType> requires MetaType<TType> struct is_one_or_const<TType> { static inline constexpr auto value = std::is_const_v<typename TType::type>; }; static_assert(Pair<int, Value<1>>{}.satisfies<is_one_or_const>());
- Template Parameters:
TPredicate – The template metafunction predicate to validate
- Returns:
whether this
Pair
satisfiesTPredicate
, as anmpl::Value
-
template<typename TPredicate>
inline constexpr auto satisfies(TPredicate &&predicate) const noexcept# Checks that this
Pair
satisfies the metafunction predicate,predicate
.Checks that this
Pair
satisfiespredicate
and returns the result as anmpl:Value<result, bool>
.If
predicate
is aMetaPredicateOf<Pair>
, invokespredicate
with thisPair
specialization and returns the result. Otherwise, checks iffirst
andsecond
separately satisfypredicate
, and returns the boolean and of those results.Example#
constexpr auto is_one_or_const = [](auto value) noexcept { if constexpr(MetaType<decltype(value)>) { return value.is_const(); } else if constexpr(MetaValue<decltype(value)>) { return Value<decltype(value)::value == 1, bool>{}; } }; static_assert(Pair<int, Value<1>>{}.satisfies(is_one_or_const));
- Template Parameters:
TPredicate – The metafunction predicate to validate
- Returns:
whether this
Pair
satisfiespredicate
, as anmpl::Value
-
template<typename TFunction>
inline constexpr auto unwrap(TFunction &&func) const noexcept -> std::invoke_result_t<TFunction, first, second># Unwraps this
Pair
intofirst
andsecond
, and invokesfunc
with them.Decomposes
this
into its constituentfirst
andsecond
metaprogramming elements and invokesfunc
, passingfirst
andsecond
as the invocation arguments, returning the result of the invocation.Requirements#
func
must be invocable withfirst, second
Example#
constexpr auto sum = [](MetaValue auto lhs, MetaValue auto rhs) noexcept { return lhs + rhs; }; static_assert(Pair<Value<1>, Value<2>>{}.unpack(sum) == 3_value);
- Template Parameters:
TFunction – the type of the function to invoke with
first
andsecond
as arguments- Parameters:
func – the function to invoke with
first
andsecond
as arguments- Returns:
The result of invoking
func
withfirst
andsecond
as arguments
-
template<std::size_t TIndex>
inline constexpr auto get() const noexcept# Returns the metaprogramming type at
TIndex
of thisPair
If
TIndex
is0
, returnsfirst
. IfTIndex
is1
, returnssecond
.Requirements#
TIndex
must be0
, or1
Example#
constexpr auto first = Pair<int, double>{}.template get<0>(); static_assert(first == decltype_<int>());
- Template Parameters:
TIndex – The index of the type to get
- Returns:
The metaprogramming type at
TIndex
of thisPair
Note
This, combined with specializations of
std::tuple_element
andstd::tuple_size
enable structured binding destructuring of this pair intofirst
andsecond
individually, as in:// we can't use structured bindings outside of function-scope, so we wrap our example // in a `constexpr` function constexpr auto example() { auto [first, second] = Pair<int, double>{}; return first == decltype_<int>() && second == decltype_<double>(); } static_assert(example());
-
template<std::size_t TIndex>
inline constexpr auto get() noexcept# Returns the metaprogramming type at
TIndex
of thisPair
If
TIndex
is0
, returnsfirst
. IfTIndex
is1
, returnssecond
.Requirements#
TIndex
must be0
, or1
Example#
constexpr auto first = Pair<int, double>{}.template get<0>(); static_assert(first == decltype_<int>());
- Template Parameters:
TIndex – The index of the type to get
- Returns:
The metaprogramming type at
TIndex
of thisPair
Note
This, combined with specializations of
std::tuple_element
andstd::tuple_size
enable structured binding destructuring of this pair intofirst
andsecond
individually, as in:// we can't use structured bindings outside of function-scope, so we wrap our example // in a `constexpr` function constexpr auto example() { auto [first, second] = Pair<int, double>{}; return first == decltype_<int>() && second == decltype_<double>(); } static_assert(example());
-
template<typename TLHSFirst, typename TLHSSecond, typename TRHSFirst, typename TRHSSecond>