hyperion::mpl::List#

group list

Hyperion provides mpl::List as a metaprogramming type for storing, communicating, working with, and operating on lists of types or values.

Example#

#include <hyperion/mpl/list.h>
#include <hyperion/mpl/metapredicates.h>

using namespace hyperion::mpl;

constexpr auto add_const = [](MetaType auto type) noexcept {
    return type.add_const();
};

constexpr auto list = List<int, double, float>{};
constexpr auto zipped = list.zip(List<u32, usize, i32>{});
constexpr auto constified = zipped.apply(add_const);

static_assert(constified == List<Pair<const int, const u32>,
                                 Pair<const double, const usize>,
                                 Pair<const float, const i32>>{});
static_assert(constified.all_of(is_const));

Exposition-Only Types#

  • struct as_meta: Exposition-only template metafunction that converts a type, TType, to the corresponding metaprogramming type, exposed via the member using alias type. Maps TType in the following manner:

    • If TType is a MetaType, maps to Type<typename as_meta<typename TType::type>::type>, else

    • If TType is a MetaValue, maps to Value<TType::value>, else

    • If TType is a MetaPair, maps to

      Pair<typename as_meta<typename TType::first>::type,
           typename as_meta<typename TType::second>::type>
      
      , else

    • Maps to Type<TType>

  • struct as_raw: Exposition-only template metafunction that converts a type, TType, to the corresponding raw type, exposed via the member using alias type. Maps TType in the following manner:

    • If TType is a MetaType, maps to typename as_raw<typename TType::type>::type, else

    • If TType is a MetaValue, maps to Value<TType::value>, else

    • If TType is a MetaPair, maps to

      Pair<typename as_raw<typename TType::first>::type,
           typename as_raw<typename TType::second>::type>
      
      , else

    • Maps to TType

Functions

template<typename ...TLHTypes, typename ...TRHTypes>
constexpr auto operator==(const List<TLHTypes...> &lhs, const List<TRHTypes...> &rhs) noexcept#

Equality comparison operator for List

Checks that each element of lhs is equal to the corresponding (by index) element of rhs, as if by equal_to(lhs.at(index))(rhs.at(index)).

Example#

static_assert(List<int, double, float>{}
              == List<int, double, float>{});
static_assert(List<Value<1, i32>, double, float>{}
              == List<Value<1, u32>, double, float>{});

Template Parameters:
  • TLHTypes – the elements of the lhs List

  • TRHTypes – the elements of the rhs List

Parameters:
  • lhs – the List to compare

  • rhs – the List to compare to

Returns:

whether the elements of lhs are equal to the elements of rhs

template<typename ...TLHTypes, typename ...TRHTypes>
constexpr auto operator!=(const List<TLHTypes...> &lhs, const List<TRHTypes...> &rhs) noexcept#

Inequality comparison operator for List

Checks that any element of lhs is not equal to the corresponding (by index) element of rhs, as if by not_equal_to(lhs.at(index))(rhs.at(index)).

Example#

static_assert(List<int, double, float>{}
              != List<float, double, float>{});
static_assert(List<Value<1, i32>, double, float>{}
              != List<Value<2, u32>, double, float>{});

Template Parameters:
  • TLHTypes – the elements of the lhs List

  • TRHTypes – the elements of the rhs List

Parameters:
  • lhs – the List to compare

  • rhs – the List to compare to

Returns:

whether any element of lhs is not equal to the corresponding element of rhs

template<typename ...TTypes>
constexpr auto make_list(TTypes&&... types) noexcept#

Creates an mpl::List representing the types of the given arguments, types

Example#

static_assert(make_list(1, 1.0, 1_usize, 1_value)
              == List<int, double, usize, Value<1_usize>>{});

Template Parameters:

TTypes – the types to store in the mpl::List

Parameters:

types – the arguments of the types to represent

Returns:

an mpl::List representing the types of the given arguments

template<typename ...TTypes>
constexpr auto make_list() noexcept#

Creates an mpl::List representing the specified types.

Example#

static_assert(make_list<int, double, usize, Value<1>, Type<int>>()
              == List<int, double, usize, Value<1>, int>{});

Template Parameters:

TTypes – the types to store in the mpl::List

Returns:

an mpl::List representing TTypes...

template<typename ...TTypes>
constexpr auto operator|(List<TTypes...> list, auto range_object)#

Pipeline operator for mpl::Lists. Provides support for piping mpl::Lists into std::ranges algorithms and views.

Example#

constexpr auto list = List<int, const double, float>{};
constexpr auto ranged
    = list
        | std::ranges::views::filter([](auto type) { return not type.is_const(); })
        | std::ranges::views::transform([](auto type) {
                return type.as_lvalue_reference().as_volatile();
          })
        | std::ranges::views::reverse
        | std::ranges::views::drop(1_value);
static_assert(ranged == List<volatile int&>{});

Template Parameters:

TTypes – the types represented in the List

Parameters:
  • list – the list to pipe into a std::ranges algorithm or view

  • range_object – the std::ranges algorithm or view to pipe into

Returns:

the result of the pipeline, up to this point

struct not_found_tag#
#include <hyperion/mpl/list.h>

Tag type indicating that a searching operation in an mpl::List could not find a/the desired result.

template<typename ...TTypes>
struct List#
#include <hyperion/mpl/list.h>

List is a metaprogramming type for storing, communicating, working with, and operating on lists of types or values.

Example#

#include <hyperion/mpl/list.h>
#include <hyperion/mpl/metapredicates.h>

using namespace hyperion::mpl;

constexpr auto add_const = [](MetaType auto type) noexcept {
    return type.add_const();
};

constexpr auto const_zipped = List<int, double, float>{}
                              .zip(List<u32, usize, i32>{})
                              .apply(add_const);
static_assert(const_zipped == List<Pair<const int, const u32>,
                                 Pair<const double, const usize>,
                                 Pair<const float, const i32>>{});
static_assert(const_zipped.all_of(is_const));

constexpr auto nums = List<Value<1>, Value<2>, Value<3>>{};
static_assert(nums.accumulate(0_value) == 6_value);

Template Parameters:

TTypes – The types to represent in the list

Public Functions

inline constexpr auto size() const noexcept#

Returns the size of this List

Returns:

the size of this List

inline constexpr auto is_empty() const noexcept#

Returns whether this List is empty.

Returns:

whether this List is empty, as a Value specialization

template<typename TFunction>
inline constexpr auto apply(TFunction &&func) const noexcept#

Applies the metafunction func to the elements of this List, returning the result as a new List specialization.

Using the exposition-only template metafunctions as_meta and as_raw (see the corresponding section in the Metaprogramming List Type module-level documentation), applies func to each element, TElement, of this List as if by typename as_raw<decltype(typename as_meta<TElement>::type{}.apply(func))>::type.

Requirements#

  • func must be a metafunction invocable with the corresponding metaprogramming type of each element in this List. That is, func must be a MetaFunctionOf<TFunction, typename as_meta<TElement>::type> for each element,TElement, of this List

  • OR, func must be a metafunction appliable to the corresponding metaprogramming type of each element in this List. That is, typename as_meta<TElement>::type{}.apply(func) must be well formed for each element, TElement, of this List

Example#

constexpr auto add_const = [](MetaType auto type) noexcept {
    return type.add_const();
};

static_assert(List<int, double>{}.apply(add_const)
              == List<const int, const double>{});

Template Parameters:

TFunction – The type of the metafunction to apply to the elements of this List

Parameters:

func – The metafunction to apply to the elements of this List

Returns:

a List specialization containing the modified elements

template<typename TVisitor>
inline constexpr auto for_each(TVisitor &&vis) const noexcept -> void#

Invokes the function vis with each element of this List.

This is the canonical way to iterate through the elements of a List.

Using the exposition-only template metafunction as_meta (see the corresponding section in the Metaprogramming List Type module-level documentation), applies vis to each element, TElement, of this List as if by vis(typename as_meta<TElement>::type{}).

Requirements#

  • vis must be invocable with the corresponding metaprogramming type for each element of this List. This is, for each element, TElement, std::invocable<TVisitor, typename as_meta<TElement>::type> must be true.

  • The invoke result of vis for each element of this List must be void.

Example#

constexpr auto example = List<Value<1>, int, float, double, int>{};
constexpr auto count_if = [](auto list, auto predicate) noexcept {
    auto num_satisfied = 0;
    list.for_each([&num_satisfied, predicate](auto element) {
        if(element.satisfies(predicate)) {
            num_satisfied++;
        }
    });
    return num_satisfied;
};

constexpr auto num_ints = count_if(example, equal_to(decltype_<int>()));
static_assert(num_ints == 2);

Template Parameters:

TVisitor – the type of the function to invoke with each element of this List

Parameters:

vis – the function to invoke with each element of this List

template<typename TVisitor, MetaValue TCount>
inline constexpr auto for_each_n(TVisitor &&vis, TCount count) const noexcept -> void#

Invokes the function vis with the first count elements of this List.

This is the canonical way to iterate through a subset of the elements of a List.

Using the exposition-only template metafunction as_meta (see the corresponding section in the Metaprogramming List Type module-level documentation), applies vis to each element, TElement, of this List as if by vis(typename as_meta<TElement>::type{}).

Requirements#

  • vis must be invocable with the corresponding metaprogramming type for each element of this List. This is, for each element, TElement, std::invocable<TVisitor, typename as_meta<TElement>::type> must be true.

  • The invoke result of vis for each element of this List must be void.

  • count must be less than or equal to the number of elements of this List

Example#

constexpr auto example = List<Value<1>, int, float, double, int>{};
constexpr auto count_if_in_first_half = [](auto list, auto predicate) noexcept {
    auto num_satisfied = 0;
    list.for_each_n([&num_satisfied, predicate](auto element) {
        if(element.satisfies(predicate)) {
            num_satisfied++;
        }
    }, list.size() / 2_value);
    return num_satisfied;
};

constexpr auto num_ints = count_if_in_first_half(example, equal_to(decltype_<int>()));
static_assert(num_ints == 1);

Template Parameters:

TVisitor – the type of the function to invoke with the first count elements of this List

Parameters:

vis – the function to invoke with the first count elements of this List

inline constexpr auto accumulate(MetaValue auto state) const noexcept#

Computes the arithmetic sum of state and the elements of this List.

Requirements#

Example#

static_assert(List<Value<1>, Value<2>, Value<3>>{}.accumulate(4_value) == 10);

Parameters:

state – the initial state to begin the summation with

Returns:

the arithmetic sum of state and the elements of this List, as a Value specialization

template<typename TDelay = List<as_meta<TTypes>...>>
inline constexpr auto accumulate(auto state, auto &&accumulator) const noexcept#

Computes the accumulation of state and the elements of this List.

Using the exposition-only template metafunction as_meta (see the corresponding section in the Metaprogramming List Type module-level documentation), and TElement_N to represent the type of each element in this List, uses the accumulation operation accumulator, performs the accumulation of the elements of this List, in order, by first invoking accumulator with as_meta<decltype(state)>{}, as_meta<TElement_0>{}, then continues to call accumulator for each successive TElement, using the result of the previous invocation as the state parameter for the next invocation in the sequence.

Requirements#

  • Using TElement_N to represent the type of each element in this List and TState to represent both decltype(state) and the (possibly different) type(s) of the return value of each possible invocation of accumulator, accumulator must be a callable taking two parameters, separately invocable with parameters of types as_meta<TState_N>, as_meta<TElement_N>, for each of all TElements and TStates. That is, the recursive call chain

    accumulator(
        accumulator(
            ...(
                accumulator(as_meta<decltype(state)>{},
                            as_meta<TElement_0>{}),
                as_meta<TElement_1>{}),
            ...),
        as_meta<TElement_N-1>{})
    
    must be well-formed.

Example#

static_assert(List<int, double, float, int>{}
              .accumulate(0_value, [](auto state, auto element) {
                // increment state if `element` is a `MetaType` representing `int`
                if constexpr(MetaType<decltype(element)>) {
                    if constexpr(decltype(element){} == decltype_<int>()) {
                        return state + 1_value;
                    }
                    else {
                        return state;
                    }
                }
                else {
                    return state;
                }
              }) == 2);

Parameters:
  • state – the initial state to begin the accumulation with

  • accumulator – the callable to perform the accumulation operation

Returns:

the accumulation of state and the elements of this List, according to accumulator

template<typename TPredicate>
inline constexpr auto find_if(TPredicate &&predicate) const noexcept#

Returns the first element of this List that satisfies the metafunction predicate predicate.

Using the exposition-only template metafunction as_meta (see the corresponding section in the Metaprogramming List Type module-level documentation), checks each element, TElement, of this List to see whether it satisfies predicate, as if by typename as_meta<TElement>::type{}.satisfies(predicate), and if satisfied, returns that element.

If no element satisfying predicate is found, returns Type<not_found_tag>

Requirements#

  • predicate must be a metapredicate invocable with the corresponding metaprogramming type of each element in this List. That is, func must be a MetaPredicateOf<TFunction, typename as_meta<TElement>::type> for each element,TElement, of this List

  • OR, predicate must be a metapredicate satisfiable with the corresponding metaprogramming type of each element in this List. That is, typename as_meta<TElement>::type{}.satisfy(predicate) must be well formed for each element, TElement, of this List

Example#

static_assert(List<int, const double, float>{}.find_if(is_const)
              == decltype_<const double>());
static_assert(List<int, const double, float>{}.find_if(is_volatile)
              == decltype_<not_found_tag>());
static_assert(List<Value<1>, Value<2>, Value<3>>{}.find_if(is_const)
              == decltype_<not_found_tag>());

Template Parameters:

TPredicate – The type of the metapredicate to use for searcch

Parameters:

predicate – The metapredicate to use for search

Returns:

the first element satisfying predicate, or Type<not_found_tag> if no element satisfies predicate

inline constexpr auto find(auto value) const noexcept#

Returns the first element of this List that is equal to value.

If no element equal to value is found, returns Type<not_found_tag>

Example#

static_assert(List<int, const double, float>{}.find(decltype_<const double>())
              == decltype_<const double>());
static_assert(List<int, const double, float>{}.find(decltype_<usize>())
              == decltype_<not_found_tag>());
static_assert(List<int, const double, float>{}.find(1_value)
              == decltype_<not_found_tag>());
static_assert(List<int, Value<1>, const double, float>{}.find(1_value)
              == 1);
static_assert(List<Value<1>, Value<2>, Value<3>>{}.find(4_value)
              == decltype_<not_found_tag>());

Parameters:

value – The metaprogramming value to search for

Returns:

the first element equal to value, or Type<not_found_tag> if no element equals value

template<typename TPredicate>
inline constexpr auto count_if(TPredicate &&predicate) const noexcept#

Returns the number of elements of this List that satisfy the metafunction predicate predicate, as a Value specialization.

Using the exposition-only template metafunction as_meta (see the corresponding section in the Metaprogramming List Type module-level documentation), checks each element, TElement, of this List to see whether it satisfies predicate, as if by typename as_meta<TElement>::type{}.satisfies(predicate), and if satisfied, increments the internal count.

Requirements#

  • predicate must be a metapredicate invocable with the corresponding metaprogramming type of each element in this List. That is, func must be a MetaPredicateOf<TFunction, typename as_meta<TElement>::type> for each element,TElement, of this List

  • OR, predicate must be a metapredicate satisfiable with the corresponding metaprogramming type of each element in this List. That is, typename as_meta<TElement>::type{}.satisfy(predicate) must be well formed for each element, TElement, of this List

Example#

static_assert(List<int, const double, float>{}.count_if(is_const)
              == 1_value);
static_assert(List<int, const double, float>{}.count_if(is_volatile)
              == 0_value);
static_assert(List<Value<1>, Value<2>, Value<3>>{}.count_if(is_const)
              == 0_value);

Template Parameters:

TPredicate – The type of the metapredicate to use

Parameters:

predicate – The metapredicate to use

Returns:

the number of elements satisfying predicate

inline constexpr auto count(auto value) const noexcept#

Returns the number of elements of this List that are equal to value, as a Value specialization.

Example#

static_assert(List<int, const double, float>{}.count(decltype_<const double>())
              == 1);
static_assert(List<int, const double, float>{}.count(decltype_<usize>())
              == 0);
static_assert(List<int, const double, float, int>{}.count(decltype_<int>())
              == 2);
static_assert(List<int, const double, float>{}.count(1_value)
              == 0);
static_assert(List<int, Value<1>, const double, float>{}.count(1_value)
              == 1);
static_assert(List<Value<1>, Value<2>, Value<3>>{}.count(4_value)
              == 0);

Parameters:

value – The metaprogramming value to search for

Returns:

the number of elements of this List that are equal to value, as a Value specialization

inline constexpr auto contains(auto value) const noexcept#

Returns whether this List contains an element equal to value, as a Value specialization.

Example#

static_assert(List<int, const double, float>{}.contains(decltype_<const double>()));
static_assert(not List<int, const double, float>{}.contains(decltype_<usize>()));
static_assert(not List<int, const double, float>{}.contains(1_value));
static_assert(List<int, Value<1>, const double, float>{}.contains(1_value));
static_assert(not List<Value<1>, Value<2>, Value<3>>{}.contains(4_value));

Parameters:

value – The metaprogramming value to search for

Returns:

whether this List contains at least one element equal to value, as a Value specialization

template<typename TPredicate>
inline constexpr auto all_of(TPredicate &&predicate) const noexcept#

Returns whether all elements of this List satisfy the metafunction predicate predicate, as a Value specialization.

Using the exposition-only template metafunction as_meta (see the corresponding section in the Metaprogramming List Type module-level documentation), checks each element, TElement, of this List to see whether it satisfies predicate, as if by typename as_meta<TElement>::type{}.satisfies(predicate).

Requirements#

  • predicate must be a metapredicate invocable with the corresponding metaprogramming type of each element in this List. That is, func must be a MetaPredicateOf<TFunction, typename as_meta<TElement>::type> for each element,TElement, of this List

  • OR, predicate must be a metapredicate satisfiable with the corresponding metaprogramming type of each element in this List. That is, typename as_meta<TElement>::type{}.satisfy(predicate) must be well formed for each element, TElement, of this List

Example#

static_assert(List<const int, const double, const float>{}.all_of(is_const));
static_assert(not List<int, const double, float>{}.all_of(is_const));
static_assert(not List<Value<1>, Value<2>, Value<3>>{}.all_of(is_const));

Template Parameters:

TPredicate – The type of the metapredicate to use

Parameters:

predicate – The metapredicate to use

Returns:

whether all elements satisfy predicate

template<typename TPredicate>
inline constexpr auto any_of(TPredicate &&predicate) const noexcept#

Returns whether any elements of this List satisfy the metafunction predicate predicate, as a Value specialization.

Using the exposition-only template metafunction as_meta (see the corresponding section in the Metaprogramming List Type module-level documentation), checks each element, TElement, of this List to see whether it satisfies predicate, as if by typename as_meta<TElement>::type{}.satisfies(predicate).

Requirements#

  • predicate must be a metapredicate invocable with the corresponding metaprogramming type of each element in this List. That is, func must be a MetaPredicateOf<TFunction, typename as_meta<TElement>::type> for each element,TElement, of this List

  • OR, predicate must be a metapredicate satisfiable with the corresponding metaprogramming type of each element in this List. That is, typename as_meta<TElement>::type{}.satisfy(predicate) must be well formed for each element, TElement, of this List

Example#

static_assert(List<const int, const double, const float>{}.any_of(is_const));
static_assert(List<int, const double, float>{}.any_of(is_const));
static_assert(not List<int, double, float>{}.any_of(is_const));
static_assert(not List<Value<1>, Value<2>, Value<3>>{}.all_of(is_const));

Template Parameters:

TPredicate – The type of the metapredicate to use

Parameters:

predicate – The metapredicate to use

Returns:

whether any elements satisfy predicate

template<typename TPredicate>
inline constexpr auto none_of(TPredicate &&predicate) const noexcept#

Returns whether zero elements of this List satisfy the metafunction predicate predicate, as a Value specialization.

Using the exposition-only template metafunction as_meta (see the corresponding section in the Metaprogramming List Type module-level documentation), checks each element, TElement, of this List to see whether it satisfies predicate, as if by typename as_meta<TElement>::type{}.satisfies(predicate).

Requirements#

  • predicate must be a metapredicate invocable with the corresponding metaprogramming type of each element in this List. That is, func must be a MetaPredicateOf<TFunction, typename as_meta<TElement>::type> for each element,TElement, of this List

  • OR, predicate must be a metapredicate satisfiable with the corresponding metaprogramming type of each element in this List. That is, typename as_meta<TElement>::type{}.satisfy(predicate) must be well formed for each element, TElement, of this List

Example#

static_assert(not List<const int, const double, const float>{}.none_of(is_const));
static_assert(not List<int, const double, float>{}.none_of(is_const));
static_assert(List<int, double, float>{}.none_of(is_const));
static_assert(List<Value<1>, Value<2>, Value<3>>{}.none_of(is_const));

Template Parameters:

TPredicate – The type of the metapredicate to use

Parameters:

predicate – The metapredicate to use

Returns:

whether zero elements satisfy predicate

template<typename TPredicate>
inline constexpr auto index_if(TPredicate &&predicate) const noexcept#

Returns the index of the first element satisfying predicate, as a Value specialization or Value<sizeof...(TTypes)> if no element satisfies predicate.

Using the exposition-only template metafunction as_meta (see the corresponding section in the Metaprogramming List Type module-level documentation), checks each element, TElement, of this List to see whether it satisfies predicate, as if by typename as_meta<TElement>::type{}.satisfies(predicate), and if satisfied, returns the index of that element.

Requirements#

  • predicate must be a metapredicate invocable with the corresponding metaprogramming type of each element in this List. That is, func must be a MetaPredicateOf<TFunction, typename as_meta<TElement>::type> for each element,TElement, of this List

  • OR, predicate must be a metapredicate satisfiable with the corresponding metaprogramming type of each element in this List. That is, typename as_meta<TElement>::type{}.satisfy(predicate) must be well formed for each element, TElement, of this List

Example#

static_assert(List<int, const double, float>{}.index_if(is_const)
              == 1_value);
static_assert(List<int, double, const float>{}.index_if(is_const)
              == 2_value);
static_assert(List<int, double, float>{}.index_if(is_const)
              == 3_value);
static_assert(List<Value<1>, Value<2>, Value<3>>{}.index_if(is_const)
              == 3_value);

Template Parameters:

TPredicate – The type of the metapredicate to use

Parameters:

predicate – The metapredicate to use

Returns:

the index of the first element to satisfy predicate, or sizeof...(TTypes) if no element satisfies predicate

inline constexpr auto index_of(auto value) const noexcept#

Returns the index of the first element of this List that is equal to value, as a Value specialization.

If no element equal to value is found, returns Value<sizeof...(TTypes)>

Example#

static_assert(List<int, const double, float>{}.index_of(decltype_<const double>())
              == 1);
static_assert(List<int, const double, float>{}.index_of(decltype_<usize>())
              == 3);
static_assert(List<int, const double, float>{}.index_of(1_value)
              == 3);
static_assert(List<int, const double, float, int>{}.index_of(decltype_<int>())
              == 0);
static_assert(List<int, Value<1>, const double, float>{}.index_of(1_value)
              == 1);
static_assert(List<Value<1>, Value<2>, Value<3>>{}.index_of(4_value)
              == 3);

Parameters:

value – The metaprogramming value to search for

Returns:

the index of the first element equal to value, or Value<sizeof...(TTypes)> if no element equals value

template<typename TPredicate>
inline constexpr auto filter(TPredicate &&predicate) const noexcept#

Returns a List containing only the elements of this List that satisfy predicate.

Using the exposition-only template metafunction as_meta (see the corresponding section in the Metaprogramming List Type module-level documentation), checks each element, TElement, of this List to see whether it satisfies predicate, as if by typename as_meta<TElement>::type{}.satisfies(predicate), and if satisfied, that element is included in the returned List.

Relative ordering of elements is maintained in the returned List.

Requirements#

  • predicate must be a metapredicate invocable with the corresponding metaprogramming type of each element in this List. That is, func must be a MetaPredicateOf<TFunction, typename as_meta<TElement>::type> for each element,TElement, of this List

  • OR, predicate must be a metapredicate satisfiable with the corresponding metaprogramming type of each element in this List. That is, typename as_meta<TElement>::type{}.satisfy(predicate) must be well formed for each element, TElement, of this List

Example#

constexpr auto is_value = [](MetaValue auto val) noexcept {
    return Value<true>{};
};

static_assert(List<int, const double, float>{}.filter(is_const)
              == List<const double>{});
static_assert(List<int, double, float>{}.filter(is_const)
              == List<>{});
static_assert(List<int, double, const float>{}.filter(is_const)
              == List<const float>{});
static_assert(List<int, Value<1>, double, Value<2>, float>{}.filter(is_value)
              == List<Value<1>, Value<2>>{});

Template Parameters:

TPredicate – The type of the metapredicate to use

Parameters:

predicate – The metapredicate to use

Returns:

the List containing only the elements of this List that satisfy predicate

template<typename TPredicate>
inline constexpr auto remove_if(TPredicate &&predicate) const noexcept#

Returns a copy of this List, but with all elements that satisfy predicate removed.

Using the exposition-only template metafunction as_meta (see the corresponding section in the Metaprogramming List Type module-level documentation), checks each element, TElement, of this List to see whether it satisfies predicate, as if by typename as_meta<TElement>::type{}.satisfies(predicate), and if satisfied, that element is not included in the returned List.

Relative ordering of elements is maintained in the returned List.

Requirements#

  • predicate must be a metapredicate invocable with the corresponding metaprogramming type of each element in this List. That is, func must be a MetaPredicateOf<TFunction, typename as_meta<TElement>::type> for each element,TElement, of this List

  • OR, predicate must be a metapredicate satisfiable with the corresponding metaprogramming type of each element in this List. That is, typename as_meta<TElement>::type{}.satisfy(predicate) must be well formed for each element, TElement, of this List

Example#

constexpr auto is_value = [](MetaValue auto val) noexcept {
    return Value<true>{};
};

static_assert(List<int, const double, float>{}.remove_if(is_const)
              == List<int, float>{});
static_assert(List<int, double, float>{}.remove_if(is_const)
              == List<int, double, float>{});
static_assert(List<int, double, const float>{}.remove_if(is_const)
              == List<int, double>{});
static_assert(List<int, Value<1>, double, Value<2>, float>{}.remove_if(is_value)
              == List<int, double, float>{});

Template Parameters:

TPredicate – The type of the metapredicate to use

Parameters:

predicate – The metapredicate to use

Returns:

a copy of this List, but with all elements that satisfy predicate removed

inline constexpr auto remove(auto value) const noexcept#

Returns a copy of this List, but with all elements that are equal to value removed.

Using the exposition-only template metafunction as_meta (see the corresponding section in the Metaprogramming List Type module-level documentation), checks each element, TElement, of this List to see whether it is equal to value, as if by typename as_meta<TElement>::type{}.satisfies(equal_to(value)), and if equal, that element is not included in the returned List.

Relative ordering of elements is maintained in the returned List.

Requirements#

  • predicate must be a metapredicate invocable with the corresponding metaprogramming type of each element in this List. That is, func must be a MetaPredicateOf<TFunction, typename as_meta<TElement>::type> for each element,TElement, of this List

  • OR, predicate must be a metapredicate satisfiable with the corresponding metaprogramming type of each element in this List. That is, typename as_meta<TElement>::type{}.satisfy(predicate) must be well formed for each element, TElement, of this List

Example#

static_assert(List<int, const double, float>{}.remove(decltype_<const double>())
              == List<int, float>{});
static_assert(List<int, double, float>{}.remove(decltype_<u32>())
              == List<int, double, float>{});
static_assert(List<int, double, const float>{}.remove(decltype_<const float>())
              == List<int, double>{});
static_assert(List<int, Value<1>, double, Value<2>, float>{}.remove(1_value)
              == List<int, double, Value<2>, float>{});

Template Parameters:

TPredicate – The type of the metapredicate to use

Parameters:

predicate – The metapredicate to use

Returns:

a copy of this List, but with all elements that are equal to value removed

template<template<typename...> typename TList, typename ...TValues>
inline constexpr auto sift(TList<TValues...> list) const noexcept#

Returns a List containing the elements of this List occurring at the indices specified in list.

Ordering of elements in the returned list follows ordering of indices specified in list.

Requirements#

  • list must be a MetaList type

  • Every element of list must be a MetaValue

  • Every element of list must have a value in the range [0, this->size())

Example#

constexpr auto sifter = List<Value<1>, Value<2>>{};

static_assert(List<int, const double, float>{}.sift(sifter)
              == List<const double, float>{});
static_assert(List<int, double, float>{}.sift(sifter)
              == List<double, float>{});
static_assert(List<int, Value<1>, double, Value<2>, float>{}.sift(sifter)
              == List<Value<1>, double>{});

Template Parameters:
  • TList – The metaprogramming list class template

  • TValues – The metaprogramming value types stored in list

Parameters:

list – The metaprogramming list containing the indices of the elements of this List to get

Returns:

a List containing the elements of this List occurring at the indices specified in list

template<typename TFunction>
inline constexpr auto unwrap(TFunction &&func) const noexcept -> std::invoke_result_t<TFunction, as_meta<TTypes>...>#

Converts the elements of this list into a parameter pack, and invokes func with that pack, returning the result of the invocation.

Requirements#

  • func must be invocable with the elements of this List as a parameter pack. That is, using the exposition-only template metafunction as_meta (see the corresponding section in the Metaprogramming List Type module-level documentation), std::invoke(std::forward<TFunction>(func), typename as_meta<TTypes>::type{}...) must be well-formed

Example#

constexpr auto sum = [](MetaValue auto... values) noexcept {
    return (values + ...);
};

static_assert(List<Value<1>, Value<2>, Value<3>>{}.unwrap(sum) == 6);

Template Parameters:

TFunction – the type of the callable to invoke

Parameters:

func – the callable to invoke with the elements of this List as the parameters

Returns:

the result of invoking func with the elements of this List

template<usize TIndex>
inline constexpr auto at() const noexcept#

Returns the element of this List at index TIndex.

Given type, type, being the element at index TIndex of this List, and using the exposition-only template metafunction as_meta (see the corresponding section in the Metaprogramming List Type module-level documentation), returns the element at index TIndex, converted to the corresponding mpl metaprogramming type, as if by return typename as_meta<type>::type{};

Requirements#

  • TIndex must be less than the size of this List

Example#

static_assert(List<int, double, float>{}.at<0>() == decltype_<int>());
static_assert(List<int, double, float>{}.at<1>() == decltype_<double>());
static_assert(List<int, double, float>{}.at<2>() == decltype_<float>());

Template Parameters:

TIndex – the index of the element to access

Returns:

the element at index TIndex

inline constexpr auto at(MetaValue auto index) const noexcept#

Returns the element of this List at index, index.

Given type, type, being the element at index, index, of this List, and using the exposition-only template metafunction as_meta (see the corresponding section in the Metaprogramming List Type module-level documentation), returns the element at index, converted to the corresponding mpl metaprogramming type, as if by return typename as_meta<type>::type{};

Requirements#

  • index must be less than the size of this List

Example#

static_assert(List<int, double, float>{}.at(0_value) == decltype_<int>());
static_assert(List<int, double, float>{}.at(1_value) == decltype_<double>());
static_assert(List<int, double, float>{}.at(2_value) == decltype_<float>());

Parameters:

index – the index of the element to access

Returns:

the element at index TIndex

inline constexpr auto front() const noexcept#

Returns the first element of this List

Given type, type, being the first element of this List, and using the exposition-only template metafunction as_meta (see the corresponding section in the Metaprogramming List Type module-level documentation), returns the first element, converted to the corresponding mpl metaprogramming type, as if by return typename as_meta<type>::type{};

Example#

static_assert(List<int, double, float>{}.front() == decltype_<int>());
static_assert(List<double, int, float>{}.front() == decltype_<double>());
static_assert(List<float, double, int>{}.front() == decltype_<float>());

Returns:

the first element of this List

inline constexpr auto back() const noexcept#

Returns the last element of this List

Given type, type, being the last element of this List, and using the exposition-only template metafunction as_meta (see the corresponding section in the Metaprogramming List Type module-level documentation), returns the last element, converted to the corresponding mpl metaprogramming type, as if by return typename as_meta<type>::type{};

Example#

static_assert(List<float, double, int>{}.back() == decltype_<int>());
static_assert(List<int, float, double>{}.back() == decltype_<double>());
static_assert(List<int, double, float>{}.back() == decltype_<float>());

Returns:

the last element of this List

inline constexpr auto push_front(MetaType auto type) const noexcept#

Returns a copy of this List, with type prepended to the beginning of the List.

Using the exposition-only template metafunction as_raw (see the corresponding section in the Metaprogramming List Type module-level documentation), returns a List containing typename as_raw<decltype(type)>::type, TTypes....

Example#

static_assert(List<float, double, int>{}.push_front(decltype_<int>())
              == List<int, float, double, int>{});
static_assert(List<float, double, int>{}.push_front(decltype_<float>())
              == List<float, float, double, int>{});
static_assert(List<float, double, int>{}.push_front(decltype_usize>())
              == List<usize, float, double, int>{});

Parameters:

type – The Type to prepend

Returns:

a copy of this List, with type prepended to the beginning of the List.

inline constexpr auto push_front(MetaValue auto value) const noexcept#

Returns a copy of this List, with value prepended to the beginning of the List.

Using the exposition-only template metafunction as_raw (see the corresponding section in the Metaprogramming List Type module-level documentation), returns a List containing typename as_raw<decltype(value)>::type, TTypes....

Example#

static_assert(List<float, double, int>{}.push_front(1_value)
              == List<Value<1>, float, double, int>{});
static_assert(List<float, double, int>{}.push_front(2_value)
              == List<Value<2>, float, double, int>{});
static_assert(List<float, double, int>{}.push_front(3_value)
              == List<Value<3>, float, double, int>{});

Parameters:

value – The Value to prepend

Returns:

a copy of this List, with value prepended to the beginning of the List.

inline constexpr auto push_front(MetaPair auto pair) const noexcept#

Returns a copy of this List, with pair prepended to the beginning of the List.

Using the exposition-only template metafunction as_raw (see the corresponding section in the Metaprogramming List Type module-level documentation), returns a List containing typename as_raw<decltype(pair)>::type, TTypes....

Example#

static_assert(List<float, double, int>{}.push_front(Pair<int, double>{})
              == List<Pair<int, double>, float, double, int>{});
static_assert(List<float, double, int>{}.push_front(Pair<Value<1>, float>{})
              == List<Pair<Value<1>, float>, float, double, int>{});
static_assert(List<float, double, int>{}.push_front(Pair<usize, void>{})
              == List<Pair<usize, void>, float, double, int>{});

Parameters:

pair – The Pair to prepend

Returns:

a copy of this List, with pair prepended to the beginning of the List.

template<typename ...TOthers>
inline constexpr auto push_front(List<TOthers...> list) const noexcept -> List<TOthers..., TTypes...>#

Returns a copy of this List, with the elements of list prepended to the beginning of the List.

Using the exposition-only template metafunction as_raw (see the corresponding section in the Metaprogramming List Type module-level documentation), returns a List containing TOthers..., TTypes....

Example#

static_assert(List<float, double, int>{}.push_front(List<Value<1>, int, double>{})
              == List<Value<1>, int, double, float, double, int>{});
static_assert(List<float, double, int>{}.push_front(List<usize, Pair<i32, f32>, i64>{})
              == List<usize, Pair<i32, f32>, i64, float, double, int>{});
static_assert(List<float, double, int>{}.push_front(List<i64, f64, Value<2>>{})
              == List<i64, f64, Value<2>, float, double, int>{});

Template Parameters:

TOthers – the elements of list

Parameters:

list – the list of elements to prepend

Returns:

a copy of this List, with the elements of list prepended to the beginning of the List.

inline constexpr auto push_back(MetaType auto type) const noexcept#

Returns a copy of this List, with type appended to the end of the List.

Using the exposition-only template metafunction as_raw (see the corresponding section in the Metaprogramming List Type module-level documentation), returns a List containing TTypes..., typename as_raw<decltype(type)>::type.

Example#

static_assert(List<float, double, int>{}.push_back(decltype_<int>())
              == List<float, double, int, int>{});
static_assert(List<float, double, int>{}.push_back(decltype_<float>())
              == List<float, double, int, float>{});
static_assert(List<float, double, int>{}.push_back(decltype_usize>())
              == List<float, double, int, usize>{});

Parameters:

type – The Type to append

Returns:

a copy of this List, with type appended to the end of the List.

inline constexpr auto push_back(MetaValue auto value) const noexcept#

Returns a copy of this List, with value appended to the end of the List.

Using the exposition-only template metafunction as_raw (see the corresponding section in the Metaprogramming List Type module-level documentation), returns a List containing TTypes..., typename as_raw<decltype(value)>::type.

Example#

static_assert(List<float, double, int>{}.push_back(1_value)
              == List<float, double, int, Value<1>>{});
static_assert(List<float, double, int>{}.push_back(2_value)
              == List<float, double, int, Value<2>>{});
static_assert(List<float, double, int>{}.push_back(3_value)
              == List<float, double, int, Value<3>>{});

Parameters:

value – The Value to append

Returns:

a copy of this List, with value appended to the end of the List.

inline constexpr auto push_back(MetaPair auto pair) const noexcept#

Returns a copy of this List, with pair appended to the end of the List.

Using the exposition-only template metafunction as_raw (see the corresponding section in the Metaprogramming List Type module-level documentation), returns a List containing TTypes..., typename as_raw<decltype(pair)>::type.

Example#

static_assert(List<float, double, int>{}.push_back(Pair<int, double>{})
              == List<float, double, int, Pair<int, double>>{});
static_assert(List<float, double, int>{}.push_back(Pair<Value<1>, float>{})
              == List<float, double, int, Pair<Value<1>, float>>{});
static_assert(List<float, double, int>{}.push_back(Pair<usize, i32>{})
              == List<float, double, int, Pair<usize, i32>>{});

Parameters:

pair – The Pair to append

Returns:

a copy of this List, with pair appended to the end of the List.

template<typename ...TOthers>
inline constexpr auto push_back(List<TOthers...> list) const noexcept -> List<TTypes..., TOthers...>#

Returns a copy of this List, with the elements of list appended to the end of the List.

Using the exposition-only template metafunction as_raw (see the corresponding section in the Metaprogramming List Type module-level documentation), returns a List containing TTypes..., TOthers....

Example#

static_assert(List<float, double, int>{}.push_back(List<Value<1>, int, double>{})
              == List<float, double, int, Value<1>, int, double>{});
static_assert(List<float, double, int>{}.push_back(List<usize, Pair<i32, f32>, i64>{})
              == List<float, double, int, usize, Pair<i32, f32>, i64>{});
static_assert(List<float, double, int>{}.push_back(List<i64, f64, Value<2>>{})
              == List<float, double, int, i64, f64, Value<2>>{});

Template Parameters:

TOthers – the elements of list

Parameters:

list – the list of elements to append

Returns:

a copy of this List, with the elements of list appended to the end of the List.

inline constexpr auto pop_front() const noexcept#

Returns a copy of this List with the first element removed.

Returns:

a copy of this List with the first element removed

inline constexpr auto pop_back() const noexcept#

Returns a copy of this List with the last element removed.

Returns:

a copy of this List with the last element removed

template<typename ...TRHTypes>
inline constexpr auto zip(List<TRHTypes...> rhs) const noexcept#

Converts the elements of this List and rhs into a single list of Pairs of elements.

Returns a List of Pairs of elements, created as if by

List<Pair<this->at(0), rhs.at(0)>,
     Pair<this->at(1), rhs.at(1)>,
     ...,
     Pair<this->at(this->size() - 1), rhs.at(rhs.size() - 1)>>{}

Requirements#

  • this List and rhs must be the same size

Example#

static_assert(List<int, double>{}.zip(List<u32, u64>{})
              == List<Pair<int, u32>, Pair<double, u64>>{});

Template Parameters:

TRHTypes – the elements of rhs

Parameters:

rhs – the List of elements to zip with the elements of this List

Returns:

a List containing the elements of this List zipped with the elements of rhs