hyperion::mpl::Type#

group type

Hyperion provides mpl::Type as a metaprogramming type for storing, communicating, working with, and operating on types.

Example#

#include <hyperion/mpl/type.h>

using namespace hyperion::mpl;

// alternatively, use `decltype_<int>()`
constexpr auto type1 = Type<int>{};
constexpr auto type2 = Type<double>{};

static_assert(not type1.is(type2));
template<typename TType>
struct Type#
#include <hyperion/mpl/type.h>

Type is a metaprogramming type wrapper used for storing, communicating, operating on, and otherwis working with types.

Example#

#include <hyperion/mpl/type.h>

using namespace hyperion::mpl;

// alternatively, use `decltype_<int>()`
constexpr auto type1 = Type<int>{};
constexpr auto type2 = Type<double>{};

static_assert(not type1.is(type2));

Template Parameters:

TType – The type to metaprogram against

Public Types

using type = TType#

The type that this Type is a metaprogramming wrapper for.

Public Functions

template<typename TDelay = type>
inline constexpr auto self() const noexcept -> Type<TDelay>#

Returns another instance of this specialization of Type

Returns:

another instance of this Type specialization

template<typename TDelay = type>
inline constexpr auto inner() const noexcept -> TDelay#

Returns the inner `MetaValue type of this Type, if this Type represents a MetaValue

Requirements#

  • type is trivially default constructible

  • type is a MetaValue

Example#

constexpr auto one_typed = delctype_(1_value);

static_assert(one_typed.inner() == 1_value);

Returns:

The inner MetaValue of this Type

template<typename TDelay = type>
inline constexpr auto has_inner() const noexcept -> bool#

Returns whether the type of this Type is also a metaprogramming type (i.e. a MetaValue), in which case you may call this->inner() to obtain that an instance of that type.

Example#

constexpr auto has_inner = decltype_(1_value);
constexpr auto no_inner = decltype_<int>();

static_assert(has_inner.has_inner());
static_assert(not no_inner.has_inner());

Returns:

Whether the type of this Type is also a metaprogramming type

template<template<typename> typename TMetaFunction>
inline constexpr auto apply() const noexcept -> detail::convert_to_meta_t<TMetaFunction<type>>#

Applies the specified template metafunction to this specialization of Type.

Applies TMetaFunction to this specialization of Type and returns the calculated metaprogramming type.

Requirements#

  • TMetaFunction must be a TypeMetaFunction:

    • It must be a template taking a single type parameter,

    • It must have a static constexpr member variable, value, or a using alias type, type

Example#

template<typename TType>
struct is_const {
    using type = Value<std::is_const<std::remove_reference_t<TType>>, bool>;
};

// Type<Value<true, bool>>
constexpr auto is_const = decltype_<const int>().apply<is_const>();

static_assert(is_const.inner());

Template Parameters:

TMetaFunction – The template metafunction to apply to this Type

Returns:

The result of applying TMetaFunction

template<template<auto> typename TMetaFunction, typename TDelay = type>
inline constexpr auto apply() const noexcept -> detail::convert_to_meta_t<TMetaFunction<TDelay::value>>#

Applies the specified template metafunction to this specialization of Type.

Applies TMetaFunction to the Value specialization this Type specialization represents, and returns the calculated metaprogramming type.

Requirements#

  • TMetaFunction must be a ValueMetaFunction:

    • It must be a template taking a single value parameter,

    • It must have a static constexpr member variable, value, or a using alias type, type

  • type must be a MetaValue

Example#

template<auto TValue>
struct is_two {
    using type = Value<TValue == 2, bool>;
};

// `was_two` is `Type<Value<true, bool>>>`
constexpr auto was_two = decltype_(2_value).apply<is_two>();

static_assert(was_two.inner());

Template Parameters:

TMetaFunction – The template metafunction to apply to this Type

Returns:

The result of applying TMetaFunction

template<typename TFunction>
inline constexpr auto apply(TFunction &&func) const noexcept -> detail::convert_to_meta_t<meta_result_t<TFunction, Type<type>>>#

Applies the given metafunction to this specialization of Type.

Applies func to this specialization of Type and returns the calculated result as a metaprogramming type.

Requirements#

  • TFunction must be a MetaFunctionOf<Type> type

    • It must be a callable with an overload taking a single Type parameter

    • The selected overload of TFunction must return either a MetaType or a MetaValue

Example#

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

constexpr auto const_int = decltype_<int>().apply(add_const); // Type<const int>

static_assert(const_int == decltype_<const int>());

constexpr auto get_size = [](MetaType auto value) {
    return value.sizeof_();
};

constexpr auto sizeof_int = decltype_<int>().apply(get_size); // Value<4, usize>

static_assert(sizeof_int == 4_usize);

Template Parameters:

TFunction – The type of the metafunction to apply

Parameters:

func – The metafunction to apply

Returns:

The result of applying func to this Type specialization, as a Type specialization

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

Applies the given metafunction to the type of this specialization of Type.

Given that type is a MetaValue, applies func to the MetaValue type of this specialization of Type, as if by type{}.apply(std::forward<TFunction>(func)).

Requirements#

  • TFunction must be a MetaFunctionOf<type> type

    • It must be a callable with an overload taking a single Type parameter

    • The selected overload of TFunction must return either a MetaType or a MetaValue

  • The result of invoking func with a Type must be a MetaType

  • typename meta_result_t<TFunction, type>::type must not be a MetaType

  • type must be a MetaValue

Example#

constexpr auto is_two = [](MetaValue auto value)
    -> Value<decltype(value)::value == 2, bool>
{
    return {};
};

constexpr auto was_two = decltype_(2_value).apply(is_two); // Value<true, bool>

static_assert(was_two);

constexpr auto is_two_typed = [](MetaValue auto value)
    -> Type<Value<decltype(value)::value == 2, bool>>
{
    return {};
};

// Value<true, bool>
constexpr auto was_two_typed = decltype_(2_value).apply(is_two_typed);

static_assert(was_two_typed);

Template Parameters:

TFunction – The type of the metafunction to apply

Parameters:

func – The metafunction to apply

Returns:

The result of applying func to this Type specialization

template<template<typename> typename TPredicate>
constexpr auto satisfies() const noexcept -> std::enable_if_t<TypeMetaFunction<TPredicate> && MetaValue<TPredicate<type>> && std::same_as<std::remove_const_t<decltype(TPredicate<type>::value)>, bool>, Value<TPredicate<type>::value, bool>>#

Checks to see if this Type specialization satisfies the given template metafunction predicate, TPredicate

Requirements#

  • TPredicate must be a TypeMetaFunction

    • It must be a template taking a single value parameter,

    • It must have a static constexpr member variable, value, or a using alias type, type

  • TPredicate<type> must be a MetaValue

  • The type of the value of TPredicate, TPredicate<type>::value, must be (possibly cv-ref qualified) bool)

Example#

template<typename TType>
struct is_const {
    static inline constexpr auto value
        = std::is_const_v<std::remove_reference_t<TType>> == 2;
};

// `not_const` is `Value<false, bool>`
constexpr auto not_const = decltype_<int>().satisfies<is_const>();
// `was_const` is `Value<true, bool>`
constexpr auto was_const = decltype_<const int>().satisfies<is_const>();

static_assert(was_const);
static_assert(not not_const);

Template Parameters:

TPredicate – The metafunction predicate to check with

Returns:

The result of checking this Type specialization against TPredicate, as a Value specialization

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

Checks to see if this Type specialization satisfies the given metafunction predicate.

Requirements#

  • If type is a MetaValue:

    • If predicate is invocable with type:

      • The value returned by invoking predicate with type must either be a MetaValue, or a Type specialization representing a MetaValue.

        • Using TValue to represent that MetaValue type, the type of the value of TValue, that is decltype(TValue::value), must be of type (possibly cv-ref qualified) bool

      • If the above conditions on the return value of predicate are not met, the program is ill-formed

    • If predicate is not invocable with type, see the case where predicate is invocable with Type<type>

  • If predicate is invocable with Type<type>:

    • The value returned by invoking predicate with Type<type> must either be a MetaValue, or a Type specialization representing a MetaValue.

      • Using TValue to represent that MetaValue type, the type of the value of TValue, that is decltype(TValue::value), must be of type (possibly cv-ref qualified) bool

    • If the above conditions on the return value of predicate are not met, the program is ill-formed

  • If predicate is not invocable with Type<type> nor type, returns Value<false>

Example#

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

constexpr auto not_const = decltype_<int>().satisfies(is_const);
constexpr auto was_const = decltype_<const int>().satisfies(is_const);
static_assert(was_const);
static_assert(not not_const);

Template Parameters:

TPredicate – The type of the metafunction predicate to check with

Parameters:

predicate – The metafunction predicate to check with Value specialization

template<typename TRhs>
constexpr auto is(const Type<TRhs> &rhs) const noexcept -> Value<std::same_as<type, TRhs>, bool>#

Returns whether this Type specialization is the same as the given one.

Checks if this is an instance of the same Type specialization as rhs, that is, whether std::same_as<type, TRhs>, and returns the result as a Value specialization.

Example#

constexpr auto int_t = decltype_<int>();

constexpr auto is_int = int_t.is(decltype_<int>());
constexpr auto is_const_int = int_t.is(decltype_<const int>());

static_assert(is_int);
static_assert(not is_const_int);

Template Parameters:

TRhs – The type of the Type specialization of rhs

Parameters:

rhs – The Type specialization to compare to

Returns:

Whether this and rhs are the same Type specialization

template<typename TRhs>
inline constexpr auto is_qualification_of(const Type<TRhs> &rhs) const noexcept#

Returns whether the type of this Type specialization is the same as, or a cv-ref qualification of, the type of the given one.

Checks if the type of this Type specialization is the (possibly cv-ref qualification of the) type of the rhs specialization, that is, whether std::same_as<std::remove_cvref_t<type>, TRhs>, and returns the result as a Value specialization.

Example#

constexpr auto int_t = decltype_<const int&>();

constexpr auto is_int = int_t.is_qualification_of(decltype_<int>());
constexpr auto is_const_int = int_t.is_qualification_of(decltype_<const int>());
constexpr auto is_constref_int = int_t.is_qualification_of(decltype_<const int&>());
constexpr auto is_double = int_t.is_qualification_of(decltype_<double>());

static_assert(is_int);
static_assert(is_const_int);
static_assert(is_constref_int);
static_assert(not is_double);

Template Parameters:

TRhs – The type of the Type specialization of rhs

Parameters:

rhs – The Type specialization to compare to

Returns:

Whether the type of this is the (possibly cv-ref qualification of the) type of rhs

template<typename TDelay = type>
constexpr auto is_const() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_const_v<std::remove_reference_t<TDelay>>, bool>>#

Returns whether the type of this Type specialization is const

Example#

constexpr auto int_t = decltype_<int>();
constexpr auto const_int_t = decltype_<const int>();

static_assert(not int_t.is_const());
static_assert(const_int_t.is_const());

Returns:

Whether the type of this is const

template<typename TDelay = type>
constexpr auto is_lvalue_reference() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_lvalue_reference_v<TDelay>, bool>>#

Returns whether the type of this Type specialization is an lvalue reference.

Example#

constexpr auto int_t = decltype_<int>();
constexpr auto intref_t = decltype_<int&>();

static_assert(not int_t.is_lvalue_reference());
static_assert(intref_t.is_lvalue_reference());

Returns:

Whether the type of this is an lvalue reference

template<typename TDelay = type>
constexpr auto is_rvalue_reference() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_rvalue_reference_v<TDelay>, bool>>#

Returns whether the type of this Type specialization is an rvalue reference.

Example#

constexpr auto int_t = decltype_<int>();
constexpr auto intrefref_t = decltype_<int&&>();

static_assert(not int_t.is_rvalue_reference());
static_assert(intrefref_t.is_rvalue_reference());

Returns:

Whether the type of this is an rvalue reference

template<typename TDelay = type>
constexpr auto is_volatile() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_volatile_v<std::remove_reference_t<TDelay>>, bool>>#

Returns whether the type of this Type specialization is volatile

Example#

constexpr auto int_t = decltype_<int>();
constexpr auto volatile_int_t = decltype_<volatile int>();

static_assert(not int_t.is_volatile());
static_assert(volatile_int_t.is_volatile());

Returns:

Whether the type of this is volatile

template<typename TDelay = type>
inline constexpr auto as_const() const noexcept#

Returns a Type specialization representing the const-qualified version of the type this specialization represents.

The application of const does not follow the same application as other mechanisms, like std::add_const, and instead follows the “intuitive” expectation that const would be applied through references. That is, whereas std::add_const<int&> would yield int&, decltype_<int&>().as_const() will yield Type<const int&>.

Example#

constexpr auto int_t = decltype_<int>();
constexpr auto const_int_t = int_t.as_const();

static_assert(const_int_t.is_const());
static_assert(const_int_t.is(decltype_<const int>()));

Returns:

the Type specialization representing const type

template<typename TDelay = type>
inline constexpr auto as_lvalue_reference() const noexcept#

Returns a Type specialization representing the lvalue reference-qualified version of the type this specialization represents.

The application of lvalue reference follows the same application as other mechanisms, like std::add_lvalue_reference, That is, where std::add_lvalue_reference<int&&> would yield int&, decltype_<int&&>().as_lvalue_reference() will also yield Type<int&>.

Example#

constexpr auto int_t = decltype_<int>();
constexpr auto intref_t = int_t.as_lvalue_reference();

static_assert(intref_t.is_lvalue_reference());
static_assert(intref_t.is(decltype_<int&>()));

Returns:

the Type specialization representing type&

template<typename TDelay = type>
inline constexpr auto as_rvalue_reference() const noexcept#

Returns a Type specialization representing the rvalue reference-qualified version of the type this specialization represents.

The application of rvalue reference does not follow the same application as other mechanisms, like std::add_rvalue_reference, That is, where std::add_rvalue_reference<int&> would yield int&, decltype_<int&>().as_rvalue_reference() will yield Type<int&&>.

Example#

constexpr auto int_t = decltype_<int>();
constexpr auto intrefref_t = int_t.as_rvalue_reference();

static_assert(intref_t.is_rvalue_reference());
static_assert(intrefref_t.is(decltype_<int&&>()));

Returns:

the Type specialization representing type&&

template<typename TDelay = type>
inline constexpr auto as_volatile() const noexcept#

Returns a Type specialization representing the volatile-qualified version of the type this specialization represents.

The application of volatile does not follow the same application as other mechanisms, like std::add_volatile, and instead follows the “intuitive” expectation that volatile would be applied through references. That is, whereas std::add_volatile<int&> would yield int&, decltype_<int&>().as_volatile() will yield Type<volatile int&>.

Example#

constexpr auto int_t = decltype_<int>();
constexpr auto volatile_int_t = int_t.as_volatile();

static_assert(volatile_int_t.is_volatile());
static_assert(volatile_int_t.is(decltype_<volatile int>()));

Returns:

the Type specialization representing volatile type

template<typename TRhs>
constexpr auto is_convertible_to(const Type<TRhs> &rhs) const noexcept -> Value<std::convertible_to<type, TRhs>, bool>#

Returns whether the type this Type specialization represents is convertible to the type rhs represents, as a Value specialization.

Example#

struct not_convertible {};
constexpr auto int_t = decltype_<int>();
constexpr auto double_t = decltype_<double>();
constexpr auto not_convertible_t = decltype_<not_convertible>();

static_assert(int_t.is_convertible_to(double_t));
static_assert(double_t.is_convertible_to(int_t));
static_assert(not int_t.is_convertible_to(not_convertible_t));
static_assert(not not_convertible_t.is_convertible_to(int_t));

Template Parameters:

TRhs – The type that rhs represents

Parameters:

rhs – The instance of the Type specialization representing the type to check that type is convertible to

Returns:

whether the type this represents is convertible to the type rhs represents, as a Value specialization

template<typename TRhs>
constexpr auto is_derived_from(const Type<TRhs> &rhs) const noexcept -> Value<std::derived_from<type, TRhs> && !std::same_as<type, TRhs>, bool>#

Returns whether the type this Type specialization represents is derived from the type rhs represents, as a Value specialization.

Example#

struct base {};
struct derived : base {};
constexpr auto int_t = decltype_<int>();
constexpr auto base_t = decltype_<base>();
constexpr auto derived_t = decltype_<base>();

static_assert(derived_t.is_derived_from(base_t));
static_assert(not base_t.is_derived_from(base_t));
static_assert(not int_t.is_derived_from(int_t));
static_assert(not int_t.is_derived_from(base_t));

Template Parameters:

TRhs – The type that rhs represents

Parameters:

rhs – The instance of the Type specialization representing the type to check that type is derived from

Returns:

whether the type this represents is derived from the type rhs represents, as a Value specialization

Note

The application of this differs from std::is_base_of or std::derived_from, in that this is false when called against the same type. That is, decltype_<base>().is_derived_from(decltype_<base>()) == false.

template<typename TRhs>
constexpr auto is_base_of(const Type<TRhs> &rhs) const noexcept -> Value<std::derived_from<TRhs, type> && !std::same_as<type, TRhs>, bool>#

Returns whether the type this Type specialization represents is a base class of the type rhs represents, as a Value specialization.

Example#

struct base {};
struct derived : base {};
constexpr auto int_t = decltype_<int>();
constexpr auto base_t = decltype_<base>();
constexpr auto derived_t = decltype_<base>();

static_assert(base_t.is_base_of(derived_t));
static_assert(not base_t.is_base_of(base_t));
static_assert(not int_t.is_base_of(int_t));
static_assert(not int_t.is_base_of(base_t));

Template Parameters:

TRhs – The type that rhs represents

Parameters:

rhs – The instance of the Type specialization representing the type to check that type is a base of

Returns:

whether the type this represents is a base of the type rhs represents, as a Value specialization

Note

The application of this differs from std::is_base_of or std::derived_from, in that this is false when called against the same type. That is, decltype_<base>().is_base_of(decltype_<base>()) == false.

template<template<typename...> typename TList, typename ...TTypes>
constexpr auto is_constructible_from(const TList<TTypes...> &list) const noexcept -> std::enable_if_t<!MetaType<TList<TTypes...>>, Value<std::is_constructible_v<type, detail::convert_to_raw_t<TTypes>...>, bool>>#

Returns whether the type this Type specialization represents is constructible from arguments of types TTypes..., as a Value specialization.

Example#

template<typename... TTypes>
struct list {};
struct tag {};
struct constructible {
    constructible(int, double, tag);
};

constexpr auto int_t = decltype_<int>();
constexpr auto constructible_t = decltype_<constructible>();

static_assert(constructible_t.is_constructible_from(list<int, double, tag>{}));
static_assert(not constructible_t.is_constructible_from(list<double>{}));
static_assert(not int_t.is_constructible_from(constructible));

Template Parameters:
  • TList – The type-list type template representing the argument types to check with

  • TTypes – The list of argument types to check with

Parameters:

list – The type-list representing the argument types to check with

Returns:

whether the type this represents is constructible from arguments of types TTypes..., as a Value specialization

template<typename ...TTypes>
constexpr auto is_constructible_from(const Type<TTypes>&... list) const noexcept -> Value<std::is_constructible_v<type, TTypes...>, bool>#

Returns whether the type this Type specialization represents is constructible from arguments of types TTypes..., as a Value specialization.

Example#

template<typename... TTypes>
struct list {};
struct tag {};
struct constructible {
    constructible(int, double, tag);
};

constexpr auto int_t = decltype_<int>();
constexpr auto constructible_t = decltype_<constructible>();

static_assert(constructible_t.is_constructible_from(decltype_<int>(),
                                                    decltype_<double>(),
                                                    decltype_<tag>()));
static_assert(not constructible_t.is_constructible_from(decltype_<double>{}));
static_assert(not int_t.is_constructible_from(constructible));

Template Parameters:

TTypes – The list of argument types to check with

Parameters:

list – The Types representing the argument types to check with

Returns:

whether the type this represents is constructible from arguments of types TTypes..., as a Value specialization

template<template<typename...> typename TList, typename ...TTypes>
constexpr auto is_noexcept_constructible_from(const TList<TTypes...> &list) const noexcept -> std::enable_if_t<!MetaType<TList<TTypes...>>, Value<std::is_nothrow_constructible_v<type, detail::convert_to_raw_t<TTypes>...>, bool>>#

Returns whether the type this Type specialization represents is noexcept constructible from arguments of types TTypes..., as a Value specialization.

Example#

template<typename... TTypes>
struct list {};
struct tag {};
struct constructible {
    constructible(int, double, tag);
    constructible(int, tag, tag) noexcept;
};

constexpr auto int_t = decltype_<int>();
constexpr auto constructible_t = decltype_<constructible>();

static_assert(constructible_t.is_noexcept_constructible_from(list<int, tag, tag>{}));
static_assert(not constructible_t
                    .is_noexcept_constructible_from(list<int, double, tag>{}));
static_assert(not constructible_t.is_noexcept_constructible_from(list<double>{}));
static_assert(not int_t.is_noexcept_constructible_from(constructible));

Template Parameters:
  • TList – The type-list type template representing the argument types to check with

  • TTypes – The list of argument types to check with

Parameters:

list – The type-list representing the argument types to check with

Returns:

whether the type this represents is noexcept constructible from arguments of types TTypes..., as a Value specialization

template<typename ...TTypes>
constexpr auto is_noexcept_constructible_from(const Type<TTypes>&... list) const noexcept -> Value<std::is_nothrow_constructible_v<type, TTypes...>, bool>#

Returns whether the type this Type specialization represents is noexcept constructible from arguments of types TTypes..., as a Value specialization.

Example#

template<typename... TTypes>
struct list {};
struct tag {};
struct constructible {
    constructible(int, double, tag);
    constructible(int, tag, tag) noexcept;
};
constexpr auto int_t = decltype_<int>();
constexpr auto constructible_t = decltype_<constructible>();

static_assert(constructible_t.is_noexcept_constructible_from(decltype_<int>(),
                                                             decltype_<tag>(),
                                                             decltype_<tag>()));
static_assert(not constructible_t.is_noexcept_constructible_from(decltype_<int>(),
                                                                 decltype_<double>(),
                                                                 decltype_<tag>()));
static_assert(not constructible_t.is_noexcept_constructible_from(decltype_<double>{}));
static_assert(not int_t.is_noexcept_constructible_from(constructible));

Template Parameters:

TTypes – The list of argument types to check with

Parameters:

list – The Types representing the argument types to check with

Returns:

whether the type this represents is noexcept constructible from arguments of types TTypes..., as a Value specialization

template<typename TDelay = type>
constexpr auto is_default_constructible() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_default_constructible_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is default constructible, as a Value specialization.

Example#

struct constructible {
    constructible();
};
struct not_constructible {
    not_constructible() = delete;
};

constexpr auto int_t = decltype_<int>();
constexpr auto constructible_t = decltype_<constructible>();
constexpr auto not_constructible_t = decltype_<not_constructible>();

static_assert(constructible_t.is_default_constructible());
static_assert(int_t.is_default_constructible());
static_assert(not not_constructible_.is_default_constructible());

Returns:

whether the type this represents is default constructible, as a Value specialization

template<typename TDelay = type>
constexpr auto is_noexcept_default_constructible() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_nothrow_default_constructible_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is noexcept default constructible, as a Value specialization.

Example#

struct constructible {
    constructible();
};
struct noexcept_constructible {
    noexcept_constructible() noexcept;
};
struct not_constructible {
    not_constructible() = delete;
};

constexpr auto int_t = decltype_<int>();
constexpr auto constructible_t = decltype_<constructible>();
constexpr auto noexcept_constructible_t = decltype_<noexcept_constructible>();
constexpr auto not_constructible_t = decltype_<not_constructible>();

static_assert(int_t.is_noexcept_default_constructible());
static_assert(noexcept_constructible_t.is_noexcept_default_constructible());
static_assert(not constructible_t.is_noexcept_default_constructible());
static_assert(not not_constructible_.is_noexcept_default_constructible());

Returns:

whether the type this represents is noexcept default constructible, as a Value specialization

template<typename TDelay = type>
constexpr auto is_trivially_default_constructible() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_trivially_default_constructible_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is trivially default constructible, as a Value specialization.

Example#

struct constructible {
    constructible();
};
struct trivially_constructible {
    trivially_constructible() = default;
};
struct not_constructible {
    not_constructible() = delete;
};

constexpr auto int_t = decltype_<int>();
constexpr auto constructible_t = decltype_<constructible>();
constexpr auto trivially_constructible_t = decltype_<trivially_constructible>();
constexpr auto not_constructible_t = decltype_<not_constructible>();

static_assert(int_t.is_trivially_default_constructible());
static_assert(trivially_constructible_t.is_trivially_default_constructible());
static_assert(not constructible_t.is_trivially_default_constructible());
static_assert(not not_constructible_.is_trivially_default_constructible());

Returns:

whether the type this represents is trivially default constructible, as a Value specialization

template<typename TDelay = type>
constexpr auto is_copy_constructible() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_copy_constructible_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is copy constructible, as a Value specialization.

Example#

struct constructible {
    constructible(const constructible&);
};
struct not_constructible {
    not_constructible(const not_constructible&) = delete;
};

constexpr auto int_t = decltype_<int>();
constexpr auto constructible_t = decltype_<constructible>();
constexpr auto not_constructible_t = decltype_<not_constructible>();

static_assert(constructible_t.is_copy_constructible());
static_assert(int_t.is_copy_constructible());
static_assert(not not_constructible_.is_copy_constructible());

Returns:

whether the type this represents is copy constructible, as a Value specialization

template<typename TDelay = type>
constexpr auto is_noexcept_copy_constructible() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_nothrow_copy_constructible_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is noexcept copy constructible, as a Value specialization.

Example#

struct constructible {
    constructible(const constructible&);
};
struct noexcept_constructible {
    noexcept_constructible(const noexcept_constructible&) noexcept;
};
struct not_constructible {
    not_constructible(const not_constructible&) = delete;
};

constexpr auto int_t = decltype_<int>();
constexpr auto constructible_t = decltype_<constructible>();
constexpr auto noexcept_constructible_t = decltype_<noexcept_constructible>();
constexpr auto not_constructible_t = decltype_<not_constructible>();

static_assert(int_t.is_noexcept_copy_constructible());
static_assert(noexcept_constructible_t.is_noexcept_copy_constructible());
static_assert(not constructible_t.is_noexcept_copy_constructible());
static_assert(not not_constructible_.is_noexcept_copy_constructible());

Returns:

whether the type this represents is noexcept copy constructible, as a Value specialization

template<typename TDelay = type>
constexpr auto is_trivially_copy_constructible() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_trivially_copy_constructible_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is trivially copy constructible, as a Value specialization.

Example#

struct constructible {
    constructible(const constructible&);
};
struct trivially_constructible {
    trivially_constructible(const trivially_constructible&) = default;
};
struct not_constructible {
    not_constructible(const not_constructible&) = delete;
};

constexpr auto int_t = decltype_<int>();
constexpr auto constructible_t = decltype_<constructible>();
constexpr auto trivially_constructible_t = decltype_<trivially_constructible>();
constexpr auto not_constructible_t = decltype_<not_constructible>();

static_assert(int_t.is_trivially_copy_constructible());
static_assert(trivially_constructible_t.is_trivially_copy_constructible());
static_assert(not constructible_t.is_trivially_copy_constructible());
static_assert(not not_constructible_.is_trivially_copy_constructible());

Returns:

whether the type this represents is trivially copy constructible, as a Value specialization

template<typename TDelay = type>
constexpr auto is_move_constructible() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_move_constructible_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is move constructible, as a Value specialization.

Example#

struct constructible {
    constructible(constructible&&);
};
struct not_constructible {
    not_constructible(not_constructible&&) = delete;
};

constexpr auto int_t = decltype_<int>();
constexpr auto constructible_t = decltype_<constructible>();
constexpr auto not_constructible_t = decltype_<not_constructible>();

static_assert(constructible_t.is_move_constructible());
static_assert(int_t.is_move_constructible());
static_assert(not not_constructible_.is_move_constructible());

Returns:

whether the type this represents is move constructible, as a Value specialization

template<typename TDelay = type>
constexpr auto is_noexcept_move_constructible() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_nothrow_move_constructible_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is noexcept move constructible, as a Value specialization.

Example#

struct constructible {
    constructible(constructible&&);
};
struct noexcept_constructible {
    noexcept_constructible(noexcept_constructible&&) noexcept;
};
struct not_constructible {
    not_constructible(not_constructible&&) = delete;
};

constexpr auto int_t = decltype_<int>();
constexpr auto constructible_t = decltype_<constructible>();
constexpr auto noexcept_constructible_t = decltype_<noexcept_constructible>();
constexpr auto not_constructible_t = decltype_<not_constructible>();

static_assert(int_t.is_noexcept_move_constructible());
static_assert(noexcept_constructible_t.is_noexcept_move_constructible());
static_assert(not constructible_t.is_noexcept_move_constructible());
static_assert(not not_constructible_.is_noexcept_move_constructible());

Returns:

whether the type this represents is noexcept move constructible, as a Value specialization

template<typename TDelay = type>
constexpr auto is_trivially_move_constructible() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_trivially_move_constructible_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is trivially move constructible, as a Value specialization.

Example#

struct constructible {
    constructible(constructible&&);
};
struct trivially_constructible {
    trivially_constructible(trivially_constructible&&) = default;
};
struct not_constructible {
    not_constructible(not_constructible&&) = delete;
};

constexpr auto int_t = decltype_<int>();
constexpr auto constructible_t = decltype_<constructible>();
constexpr auto trivially_constructible_t = decltype_<trivially_constructible>();
constexpr auto not_constructible_t = decltype_<not_constructible>();

static_assert(int_t.is_trivially_move_constructible());
static_assert(trivially_constructible_t.is_trivially_move_constructible());
static_assert(not constructible_t.is_trivially_move_constructible());
static_assert(not not_constructible_.is_trivially_move_constructible());

Returns:

whether the type this represents is trivially move constructible, as a Value specialization

template<typename TDelay = type>
constexpr auto is_copy_assignable() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_copy_assignable_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is copy assignable, as a Value specialization.

Example#

struct assignable {
    auto operator=(const assignable&) -> assignable&;
};
struct not_assignable {
    auto operator=(const not_assignable&) -> not_assignable& = delete;
};

constexpr auto int_t = decltype_<int>();
constexpr auto assignable_t = decltype_<assignable>();
constexpr auto not_assignable_t = decltype_<not_assignable>();

static_assert(assignable_t.is_copy_assignable());
static_assert(int_t.is_copy_assignable());
static_assert(not not_assignable_.is_copy_assignable());

Returns:

whether the type this represents is copy assignable, as a Value specialization

template<typename TDelay = type>
constexpr auto is_noexcept_copy_assignable() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_nothrow_copy_assignable_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is noexcept copy assignable, as a Value specialization.

Example#

struct assignable {
    auto operator=(const assignable&) -> assignable&;
};
struct noexcept_assignable {
    auto operator=(const noexcept_assignable&) noexcept -> noexcept_assignable&;
};
struct not_assignable {
    auto operator=(const not_assignable&) -> not_assignable& = delete;
};

constexpr auto int_t = decltype_<int>();
constexpr auto assignable_t = decltype_<assignable>();
constexpr auto noexcept_assignable_t = decltype_<noexcept_assignable>();
constexpr auto not_assignable_t = decltype_<not_assignable>();

static_assert(int_t.is_noexcept_copy_assignable());
static_assert(noexcept_assignable_t.is_noexcept_copy_assignable());
static_assert(not assignable_t.is_noexcept_copy_assignable());
static_assert(not not_assignable_.is_noexcept_copy_assignable());

Returns:

whether the type this represents is noexcept copy assignable, as a Value specialization

template<typename TDelay = type>
constexpr auto is_trivially_copy_assignable() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_trivially_copy_assignable_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is trivially copy assignable, as a Value specialization.

Example#

struct assignable {
    auto operator=(const assignable&) -> assignable&;
};
struct trivially_assignable {
    auto operator=(const trivially_assignable&) -> trivially_assignable& = default;
};
struct not_assignable {
    auto operator=(const not_assignable&) -> not_assignable& = delete;
};

constexpr auto int_t = decltype_<int>();
constexpr auto assignable_t = decltype_<assignable>();
constexpr auto trivially_assignable_t = decltype_<trivially_assignable>();
constexpr auto not_assignable_t = decltype_<not_assignable>();

static_assert(int_t.is_trivially_copy_assignable());
static_assert(trivially_assignable_t.is_trivially_copy_assignable());
static_assert(not assignable_t.is_trivially_copy_assignable());
static_assert(not not_assignable_.is_trivially_copy_assignable());

Returns:

whether the type this represents is trivially copy assignable, as a Value specialization

template<typename TDelay = type>
constexpr auto is_move_assignable() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_move_assignable_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is move assignable, as a Value specialization.

Example#

struct assignable {
    auto operator=(assignable&&) -> assignable&;
};
struct not_assignable {
    auto operator=(not_assignable&&) -> not_assignable& = delete;
};

constexpr auto int_t = decltype_<int>();
constexpr auto assignable_t = decltype_<assignable>();
constexpr auto not_assignable_t = decltype_<not_assignable>();

static_assert(assignable_t.is_move_assignable());
static_assert(int_t.is_move_assignable());
static_assert(not not_assignable_.is_move_assignable());

Returns:

whether the type this represents is move assignable, as a Value specialization

template<typename TDelay = type>
constexpr auto is_noexcept_move_assignable() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_nothrow_move_assignable_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is noexcept move assignable, as a Value specialization.

Example#

struct assignable {
    auto operator=(assignable&&) -> assignable&;
};
struct noexcept_assignable {
    auto operator=(noexcept_assignable&&) noexcept -> noexcept_assignable&;
};
struct not_assignable {
    auto operator=(not_assignable&&) -> not_assignable& = delete;
};

constexpr auto int_t = decltype_<int>();
constexpr auto assignable_t = decltype_<assignable>();
constexpr auto noexcept_assignable_t = decltype_<noexcept_assignable>();
constexpr auto not_assignable_t = decltype_<not_assignable>();

static_assert(int_t.is_noexcept_move_assignable());
static_assert(noexcept_assignable_t.is_noexcept_move_assignable());
static_assert(not assignable_t.is_noexcept_move_assignable());
static_assert(not not_assignable_.is_noexcept_move_assignable());

Returns:

whether the type this represents is noexcept move assignable, as a Value specialization

template<typename TDelay = type>
constexpr auto is_trivially_move_assignable() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_trivially_move_assignable_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is trivially move assignable, as a Value specialization.

Example#

struct assignable {
    auto operator=(assignable&&) -> assignable&;
};
struct trivially_assignable {
    auto operator=(trivially_assignable&&) -> trivially_assignable& = default;
};
struct not_assignable {
    auto operator=(not_assignable&&) -> not_assignable& = delete;
};

constexpr auto int_t = decltype_<int>();
constexpr auto assignable_t = decltype_<assignable>();
constexpr auto trivially_assignable_t = decltype_<trivially_assignable>();
constexpr auto not_assignable_t = decltype_<not_assignable>();

static_assert(int_t.is_trivially_move_assignable());
static_assert(trivially_assignable_t.is_trivially_move_assignable());
static_assert(not assignable_t.is_trivially_move_assignable());
static_assert(not not_assignable_.is_trivially_move_assignable());

Returns:

whether the type this represents is trivially move assignable, as a Value specialization

template<typename TDelay = type>
constexpr auto is_destructible() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_destructible_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is destructible, as a Value specialization.

Example#

struct destructible {
    ~destructible();
};
struct not_destructible {
    ~not_destructible() = delete;
};

constexpr auto int_t = decltype_<int>();
constexpr auto destructible_t = decltype_<destructible>();
constexpr auto not_destructible_t = decltype_<not_destructible>();

static_assert(destructible_t.is_destructible());
static_assert(int_t.is_destructible());
static_assert(not not_destructible_.is_destructible());

Returns:

whether the type this represents is destructible, as a Value specialization

template<typename TDelay = type>
constexpr auto is_noexcept_destructible() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_nothrow_destructible_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is noexcept destructible, as a Value specialization.

Example#

struct destructible {
    ~destructible();
};
struct noexcept_destructible {
    ~noexcept_destructible() noexcept;
};
struct not_destructible {
    ~not_destructible() = delete;
};

constexpr auto int_t = decltype_<int>();
constexpr auto destructible_t = decltype_<destructible>();
constexpr auto noexcept_destructible_t = decltype_<noexcept_destructible>();
constexpr auto not_destructible_t = decltype_<not_destructible>();

static_assert(int_t.is_noexcept_destructible());
static_assert(noexcept_destructible_t.is_noexcept_destructible());
static_assert(not destructible_t.is_noexcept_destructible());
static_assert(not not_destructible_.is_noexcept_destructible());

Returns:

whether the type this represents is noexcept destructible, as a Value specialization

template<typename TDelay = type>
constexpr auto is_trivially_destructible() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_trivially_destructible_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is trivially destructible, as a Value specialization.

Example#

struct destructible {
    ~destructible();
}
struct trivially_destructible {
    ~trivially_destructible() = default;
}
struct not_destructible {
    ~not_destructible() = delete;
}
constexpr auto int_t = decltype_<int>();
constexpr auto destructible_t = decltype_<destructible>();
constexpr auto trivially_destructible_t = decltype_<trivially_destructible>();
constexpr auto not_destructible_t = decltype_<not_destructible>();

static_assert(int_t.is_trivially_destructible());
static_assert(trivially_destructible_t.is_trivially_destructible());
static_assert(not destructible_t.is_trivially_destructible());
static_assert(not not_destructible_.is_trivially_destructible());

Returns:

whether the type this represents is trivially destructible, as a Value specialization

template<typename TDelay = type>
constexpr auto is_swappable() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_swappable_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is swappable, as a Value specialization.

If type is swappable, i.e., given lhs and rhs that are both type&, std::swap(lhs, rhs) is well-formed, returns Value<true>. Otherwise, returns Value<false>.

Example#

struct not_swappable {
    friend void swap(not_swappable&, not_swappable&) = delete;
};
struct swappable {
    friend void swap(swappable&, swappable&);
};

static constexpr auto swappable_t = decltype_<swappable>();
static constexpr auto not_swappable_t = decltype_<not_swappable>();

static_assert(swappable_t.is_swappable());
static_assert(not not_swappable_t.is_swappable());

Returns:

whether the type this represents is swappable, as a Value specialization

template<typename TDelay = type>
constexpr auto is_noexcept_swappable() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<std::is_nothrow_swappable_v<TDelay>, bool>>#

Returns whether the type this Type specialization represents is noexcept swappable, as a Value specialization.

If type is noexcept swappable, i.e., given lhs and rhs that are both type&, std::swap(lhs, rhs) is both well-formed and noexcept, returns Value<true>. Otherwise, returns Value<false>.

Example#

struct not_swappable {
    friend void swap(not_swappable&, not_swappable&) = delete;
};
struct swappable {
    friend void swap(swappable&, swappable&);
};
struct noexcept_swappable {
    friend void swap(noexcept_swappable&, noexcept_swappable&) noexcept;
};

static constexpr auto swappable_t = decltype_<swappable>();
static constexpr auto noexcept_swappable_t = decltype_<noexcept_swappable>();
static constexpr auto not_swappable_t = decltype_<not_swappable>();

static_assert(noexcept_swappable_t.is_noexcept_swappable());
static_assert(not swappable_t.is_noexcept_swappable());
static_assert(not not_swappable_t.is_noexcept_swappable());

Returns:

whether the type this represents is swappable, as a Value specialization

template<typename TRhs = type>
constexpr auto is_swappable_with(const Type<TRhs> &rhs = Type<TRhs>{}) const noexcept -> Value<std::is_swappable_with_v<std::conditional_t<std::is_reference_v<type>, type, std::add_lvalue_reference_t<type>>, std::conditional_t<std::is_reference_v<TRhs>, TRhs, std::add_lvalue_reference_t<TRhs>>>, bool>#

Returns whether the type this Type specialization represents is swappable with the type rhs represents, as a Value specialization.

If the type this represents is swappable with the type rhs represents, i.e., given val1 and val2 that are type& and TRhs&, respectively, std::swap(lhs, rhs) is well-formed, returns Value<true>. Otherwise, returns Value<false>.

Example#

struct not_swappable {
    friend void swap(not_swappable&, int&) = delete;
};
struct swappable {
    friend void swap(swappable&, int&);
    friend void swap(int&, swappable&);
};

static constexpr auto swappable_t = decltype_<swappable>();
static constexpr auto not_swappable_t = decltype_<not_swappable>();

static_assert(swappable_t.is_swappable_with(decltype_<int>()));
static_assert(not not_swappable_t.is_swappable_with(decltype_<int>()));

Template Parameters:

TRhs – The type to check that type is swappable with

Parameters:

rhs – The Type specialization representing the type to check that type is swappable with

Returns:

whether the type this represents is swappable with the type rhs represents, as a Value specialization

template<typename TRhs = type>
constexpr auto is_noexcept_swappable_with(const Type<TRhs> &rhs = Type<TRhs>{}) const noexcept -> Value<std::is_nothrow_swappable_with_v<std::conditional_t<std::is_reference_v<type>, type, std::add_lvalue_reference_t<type>>, std::conditional_t<std::is_reference_v<TRhs>, TRhs, std::add_lvalue_reference_t<TRhs>>>, bool>#

Returns whether the type this Type specialization represents is noexcept swappable with the type rhs represents, as a Value specialization.

If the type this represents is noexcept swappable with the type rhs represents, i.e., given val1 and val2 that are type& and TRhs&, respectively, std::swap(lhs, rhs) is both well-formed and noexcept, returns Value<true>. Otherwise, returns Value<false>.

Example#

struct not_swappable {
    friend void swap(not_swappable&, int&) = delete;
};
struct swappable {
    friend void swap(swappable&, int&);
    friend void swap(int&, swappable&);
};
struct noexcept_swappable {
    friend void swap(swappable&, int&) noexcept;
    friend void swap(int&, swappable&) noexcept;
};

static constexpr auto swappable_t = decltype_<swappable>();
static constexpr auto noexcept_swappable_t = decltype_<swappable>();
static constexpr auto not_swappable_t = decltype_<not_swappable>();

static_assert(noexcept_swappable_t.is_noexcept_swappable_with(decltype_<int>()));
static_assert(not swappable_t.is_noexcept_swappable_with(decltype_<int>()));
static_assert(not not_swappable_t.is_noexcept_swappable_with(decltype_<int>()));

Template Parameters:

TRhs – The type to check that type is noexcept swappable with

Parameters:

rhs – The Type specialization representing the type to check that type is noexcept swappable with

Returns:

whether the type this represents is noexcept swappable with the type rhs represents, as a Value specialization

template<typename TDelay = type>
constexpr auto sizeof_() const noexcept -> std::enable_if_t<std::same_as<TDelay, type>, Value<sizeof(TDelay), usize>>#

Returns the sizeof the type this Type specialization represents, as a Value specialization.

Returns:

the sizeof the type this represents, as a Value specialization