2017-06-07 00:02:25 +03:00
|
|
|
////
|
2019-02-15 03:09:07 +02:00
|
|
|
Copyright 2017, 2019 Peter Dimov
|
2017-03-14 22:57:07 +02:00
|
|
|
|
2017-06-07 00:02:25 +03:00
|
|
|
Distributed under the Boost Software License, Version 1.0.
|
|
|
|
|
|
|
|
|
|
See accompanying file LICENSE_1_0.txt or copy at
|
|
|
|
|
http://www.boost.org/LICENSE_1_0.txt
|
|
|
|
|
////
|
|
|
|
|
|
|
|
|
|
[#utility]
|
|
|
|
|
# Utility Components, <boost/mp11/utility.hpp>
|
|
|
|
|
:toc:
|
2017-06-07 00:13:13 +03:00
|
|
|
:toc-title:
|
2017-06-07 00:02:25 +03:00
|
|
|
:idprefix:
|
|
|
|
|
|
|
|
|
|
## mp_identity<T>
|
2017-03-14 22:57:07 +02:00
|
|
|
|
|
|
|
|
template<class T> struct mp_identity
|
|
|
|
|
{
|
|
|
|
|
using type = T;
|
|
|
|
|
};
|
|
|
|
|
|
2017-06-10 03:44:31 +03:00
|
|
|
`mp_identity` is a simple _transformation type trait_ (as per the C++ standard)
|
|
|
|
|
that just returns the same type. It's useful both as such, and as a type wrapper
|
2017-10-14 16:20:36 +03:00
|
|
|
for passing types as values to functions.
|
2017-06-10 03:44:31 +03:00
|
|
|
|
|
|
|
|
.Using mp_identity as a type trait
|
|
|
|
|
```
|
|
|
|
|
template<class T> using addp_if_not_ref =
|
|
|
|
|
typename mp_if<std::is_reference<T>, mp_identity<T>, std::add_pointer<T>>::type;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
.Using mp_identity to protect qualifiers and references
|
|
|
|
|
```
|
|
|
|
|
template<class T> void print1()
|
|
|
|
|
{
|
|
|
|
|
std::cout << typeid(T).name() << std::endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class T> void print2()
|
|
|
|
|
{
|
|
|
|
|
std::cout << typeid(mp_identity<T>).name() << std::endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main()
|
|
|
|
|
{
|
|
|
|
|
print1<int const&>(); // 'int'
|
|
|
|
|
print2<int const&>(); // 'mp_identity<int const &>'
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2017-06-07 00:02:25 +03:00
|
|
|
## mp_identity_t<T>
|
|
|
|
|
|
2017-06-10 04:13:39 +03:00
|
|
|
template<class T> using mp_identity_t = typename mp_identity<T>::type;
|
2017-03-14 22:57:07 +02:00
|
|
|
|
2017-06-07 00:02:25 +03:00
|
|
|
## mp_inherit<T...>
|
|
|
|
|
|
2017-03-14 22:57:07 +02:00
|
|
|
template<class... T> struct mp_inherit: T... {};
|
|
|
|
|
|
2017-06-07 00:02:25 +03:00
|
|
|
## mp_if_c<C, T, E...>
|
|
|
|
|
|
2017-05-18 14:59:46 +03:00
|
|
|
template<bool C, class T, class... E> using mp_if_c = /*...*/;
|
2017-03-14 22:57:07 +02:00
|
|
|
|
2017-05-18 14:59:46 +03:00
|
|
|
`mp_if_c<true, T, E...>` is an alias for `T`. `mp_if_c<false, T, E>` is an alias for `E`. Otherwise, the result is a substitution failure.
|
|
|
|
|
|
2017-06-10 03:44:31 +03:00
|
|
|
.Using mp_if_c to select between two alternatives
|
|
|
|
|
```
|
|
|
|
|
using R1 = mp_if_c<true, int, void>; // int
|
2017-06-09 20:35:21 +03:00
|
|
|
|
2017-06-10 03:44:31 +03:00
|
|
|
using R2 = mp_if_c<false, int, void>; // void
|
|
|
|
|
```
|
2017-05-18 14:59:46 +03:00
|
|
|
|
2017-06-10 03:44:31 +03:00
|
|
|
.Using mp_if_c to fail substitution when a condition is not met
|
|
|
|
|
```
|
|
|
|
|
template<class I> using void_if_5 = mp_if_c<I::value == 5, void>;
|
|
|
|
|
```
|
|
|
|
|
This example returns `void` when `I::value` is 5, and generates a substitution failure
|
|
|
|
|
otherwise. It's the same as `std::enable_if_t<I::value == 5>` in {cpp}14, or
|
|
|
|
|
`typename std::enable_if<I::value == 5>::type` in {cpp}11.
|
2017-03-14 22:57:07 +02:00
|
|
|
|
2017-06-07 00:02:25 +03:00
|
|
|
## mp_if<C, T, E...>
|
|
|
|
|
|
2018-02-07 20:56:47 +02:00
|
|
|
template<class C, class T, class... E> using mp_if =
|
2017-06-09 20:35:21 +03:00
|
|
|
mp_if_c<static_cast<bool>(C::value), T, E...>;
|
2017-03-14 22:57:07 +02:00
|
|
|
|
2017-05-18 14:59:46 +03:00
|
|
|
Like `mp_if_c`, but the first argument is a type.
|
2017-03-14 22:57:07 +02:00
|
|
|
|
2017-06-10 03:44:31 +03:00
|
|
|
.Using mp_if to select between two alternatives
|
|
|
|
|
```
|
|
|
|
|
using R1 = mp_if<mp_true, int, void>; // int
|
|
|
|
|
|
|
|
|
|
using R2 = mp_if<mp_false, int, void>; // void
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
.Using mp_if to fail substitution when a condition is not met
|
|
|
|
|
```
|
|
|
|
|
template<class T> using void_if_const = mp_if<std::is_const<T>, void>;
|
|
|
|
|
|
|
|
|
|
template<class... T> using void_if_all_const =
|
|
|
|
|
mp_if<mp_all<std::is_const<T>...>, void>;
|
|
|
|
|
|
|
|
|
|
template<class T> using if_non_const = mp_if<mp_not<std::is_const<T>>, T>;
|
|
|
|
|
```
|
|
|
|
|
|
2017-06-07 00:02:25 +03:00
|
|
|
## mp_eval_if_c<C, T, F, U...>
|
|
|
|
|
|
2017-06-10 03:44:31 +03:00
|
|
|
template<bool C, class T, template<class...> class F, class... U> using mp_eval_if_c =
|
|
|
|
|
/*...*/;
|
2017-03-14 22:57:07 +02:00
|
|
|
|
2017-05-19 03:22:53 +03:00
|
|
|
`mp_eval_if_c<C, T, F, U...>` is an alias for `T` when `C` is `true`, for `F<U...>` otherwise. Its purpose
|
2017-03-14 22:57:07 +02:00
|
|
|
is to avoid evaluating `F<U...>` when the condition is `true` as it may not be valid in this case.
|
|
|
|
|
|
2017-06-10 03:44:31 +03:00
|
|
|
.Using mp_eval_if_c to select the first pack element, or void
|
|
|
|
|
```
|
|
|
|
|
template<class... T> using first_or_void =
|
|
|
|
|
mp_eval_if_c<sizeof...(T) == 0, void, mp_apply, mp_first, mp_list<T...>>;
|
|
|
|
|
```
|
|
|
|
|
|
2017-06-07 00:02:25 +03:00
|
|
|
## mp_eval_if<C, T, F, U...>
|
|
|
|
|
|
2017-06-09 20:35:21 +03:00
|
|
|
template<class C, class T, template<class...> class F, class... U> using mp_eval_if =
|
|
|
|
|
mp_eval_if_c<static_cast<bool>(C::value), T, F, U...>;
|
2017-03-14 22:57:07 +02:00
|
|
|
|
|
|
|
|
Like `mp_eval_if_c`, but the first argument is a type.
|
|
|
|
|
|
2017-06-10 03:44:31 +03:00
|
|
|
.Using mp_eval_if to select the first list element, or void
|
|
|
|
|
```
|
|
|
|
|
template<class L> using first_or_void = mp_eval_if<mp_empty<L>, void, mp_first, L>;
|
|
|
|
|
```
|
|
|
|
|
|
2017-06-07 00:02:25 +03:00
|
|
|
## mp_eval_if_q<C, T, Q, U...>
|
|
|
|
|
|
2017-06-09 20:35:21 +03:00
|
|
|
template<class C, class T, class Q, class... U> using mp_eval_if_q =
|
|
|
|
|
mp_eval_if<C, T, Q::template fn, U...>;
|
2017-05-19 03:22:53 +03:00
|
|
|
|
|
|
|
|
Like `mp_eval_if`, but takes a quoted metafunction.
|
|
|
|
|
|
2019-02-15 03:09:07 +02:00
|
|
|
## mp_eval_if_not<C, T, F, U...>
|
|
|
|
|
|
|
|
|
|
template<class C, class T, template<class...> class F, class... U>
|
|
|
|
|
using mp_eval_if_not = mp_eval_if<mp_not<C>, T, F, U...>;
|
|
|
|
|
|
|
|
|
|
Same as `mp_eval_if`, but the condition is reversed.
|
|
|
|
|
|
|
|
|
|
## mp_eval_if_not_q<C, T, Q, U...>
|
|
|
|
|
|
|
|
|
|
template<class C, class T, class Q, class... U> using mp_eval_if_not_q =
|
|
|
|
|
mp_eval_if_not<C, T, Q::template fn, U...>;
|
|
|
|
|
|
|
|
|
|
Same as `mp_eval_if_not`, but takes a quoted metafunction.
|
|
|
|
|
|
|
|
|
|
## mp_valid<F, T...>
|
|
|
|
|
|
|
|
|
|
template<template<class...> class F, class... T> using mp_valid = /*...*/;
|
|
|
|
|
|
|
|
|
|
`mp_valid<F, T...>` is an alias for `mp_true` when `F<T...>` is a valid expression, for `mp_false` otherwise.
|
|
|
|
|
|
|
|
|
|
.Using mp_valid to write a metafunction that checks for the existence of a nested type
|
|
|
|
|
```
|
|
|
|
|
template<class T> using get_nested_type = typename T::type;
|
|
|
|
|
|
|
|
|
|
template<class T> struct has_nested_type: mp_valid<get_nested_type, T> {};
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## mp_valid_q<Q, T...>
|
|
|
|
|
|
|
|
|
|
template<class Q, class... T> using mp_valid_q = mp_valid<Q::template fn, T...>;
|
|
|
|
|
|
|
|
|
|
Like `mp_valid`, but takes a quoted metafunction.
|
|
|
|
|
|
|
|
|
|
## mp_eval_or<T, F, U...>
|
|
|
|
|
|
|
|
|
|
template<class T, template<class...> class F, class... U> using mp_eval_or =
|
|
|
|
|
mp_eval_if_not<mp_valid<F, U...>, T, F, U...>;
|
|
|
|
|
|
|
|
|
|
`mp_eval_or<T, F, U...>` is an alias for `F<U...>` when this expression is valid, for `T` otherwise.
|
|
|
|
|
|
|
|
|
|
## mp_eval_or_q<T, Q, U...>
|
|
|
|
|
|
|
|
|
|
template<class T, class Q, class... U> using mp_eval_or_q =
|
|
|
|
|
mp_eval_or<T, Q::template fn, U...>;
|
|
|
|
|
|
|
|
|
|
Like `mp_eval_or`, but takes a quoted metafunction.
|
|
|
|
|
|
2017-10-14 16:20:36 +03:00
|
|
|
## mp_cond<C, T, R...>
|
|
|
|
|
|
|
|
|
|
template<class C, class T, class... R> using mp_cond = /*...*/;
|
|
|
|
|
|
|
|
|
|
`mp_cond<C, T, R...>` is an alias for `T` when `static_cast<bool>(C::value)` is `true`.
|
|
|
|
|
When `static_cast<bool>(C::value)` is `false`, it's an alias for `mp_cond<R...>`.
|
|
|
|
|
|
|
|
|
|
(If `static_cast<bool>(C::value)` is a substitution failure, the result is too a substitution
|
|
|
|
|
failure.)
|
|
|
|
|
|
|
|
|
|
.Using mp_cond
|
|
|
|
|
```
|
|
|
|
|
template<int N> using unsigned_ = mp_cond<
|
|
|
|
|
mp_bool<N == 8>, uint8_t,
|
|
|
|
|
mp_bool<N == 16>, uint16_t,
|
|
|
|
|
mp_bool<N == 32>, uint32_t,
|
|
|
|
|
mp_bool<N == 64>, uint64_t,
|
|
|
|
|
mp_true, unsigned // default case
|
|
|
|
|
>;
|
|
|
|
|
```
|
|
|
|
|
|
2017-06-07 00:02:25 +03:00
|
|
|
## mp_defer<F, T...>
|
|
|
|
|
|
2017-03-14 22:57:07 +02:00
|
|
|
template<template<class...> class F, class... T> using mp_defer = /*...*/;
|
|
|
|
|
|
|
|
|
|
When `mp_valid<F, T...>` is `mp_true`, `mp_defer<F, T...>` is a struct with a nested type `type` which is an alias for `F<T...>`. Otherwise,
|
|
|
|
|
`mp_defer<F, T...>` is an empty struct.
|
|
|
|
|
|
2017-06-07 00:02:25 +03:00
|
|
|
## mp_quote<F>
|
|
|
|
|
|
2017-05-12 19:43:03 +03:00
|
|
|
template<template<class...> class F> struct mp_quote
|
2017-03-14 22:57:07 +02:00
|
|
|
{
|
2017-05-12 19:43:03 +03:00
|
|
|
template<class... T> using fn = F<T...>;
|
2017-03-14 22:57:07 +02:00
|
|
|
};
|
|
|
|
|
|
2019-02-15 03:09:07 +02:00
|
|
|
`mp_quote<F>` transforms the template `F` into a _quoted metafunction_, a type with a nested template `fn` such that `fn<T...>` returns `F<T...>`.
|
2017-03-14 22:57:07 +02:00
|
|
|
|
2017-06-10 03:44:31 +03:00
|
|
|
.Using mp_quote to make a list of metafunctions
|
|
|
|
|
```
|
|
|
|
|
using LQ = mp_list<mp_quote<std::is_const>, mp_quote<std::is_volatile>>;
|
|
|
|
|
```
|
|
|
|
|
|
2017-06-26 16:15:43 +03:00
|
|
|
## mp_quote_trait<F>
|
|
|
|
|
|
|
|
|
|
template<template<class...> class F> struct mp_quote_trait
|
|
|
|
|
{
|
|
|
|
|
template<class... T> using fn = typename F<T...>::type;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
`mp_quote_trait<F>` transforms the C++03-style trait `F` into a quoted metafunction.
|
|
|
|
|
|
|
|
|
|
.Using mp_quote_trait with std::add_pointer
|
|
|
|
|
```
|
|
|
|
|
using L1 = mp_list<int, void, float>;
|
|
|
|
|
using R1 = mp_transform_q<mp_quote_trait<std::add_pointer>, L1>;
|
|
|
|
|
// mp_list<int*, void*, float*>
|
|
|
|
|
```
|
|
|
|
|
|
2019-01-07 03:41:29 +02:00
|
|
|
## mp_invoke_q<Q, T...>
|
2017-06-07 00:02:25 +03:00
|
|
|
|
2019-01-07 03:41:29 +02:00
|
|
|
template<class Q, class... T> using mp_invoke_q = typename Q::template fn<T...>;
|
2017-03-14 22:57:07 +02:00
|
|
|
|
2019-01-07 03:41:29 +02:00
|
|
|
`mp_invoke_q<Q, T...>` evaluates the nested template `fn` of a quoted metafunction. `mp_invoke_q<mp_quote<F>, T...>` returns `F<T...>`.
|
2017-06-10 03:44:31 +03:00
|
|
|
|
2019-01-07 03:41:29 +02:00
|
|
|
.Using mp_invoke_q to invoke a list of metafunctions, technique 1
|
2017-06-10 03:44:31 +03:00
|
|
|
```
|
|
|
|
|
using LQ = mp_list<mp_quote<std::is_const>, mp_quote<std::is_volatile>>;
|
|
|
|
|
|
|
|
|
|
template<class T> using is_const_and_volatile =
|
2019-01-07 03:41:29 +02:00
|
|
|
mp_all<mp_product<mp_invoke_q, LQ, mp_list<T>>>;
|
2017-06-10 03:44:31 +03:00
|
|
|
```
|
|
|
|
|
|
2019-01-07 03:41:29 +02:00
|
|
|
.Using mp_invoke_q to invoke a list of metafunctions, technique 2
|
2017-06-10 03:44:31 +03:00
|
|
|
```
|
|
|
|
|
template<class T> using is_const_and_volatile =
|
2019-01-07 03:41:29 +02:00
|
|
|
mp_all<mp_transform_q<mp_bind_back<mp_invoke_q, T>, LQ>>;
|
2017-06-10 03:44:31 +03:00
|
|
|
```
|
|
|
|
|
|
2019-01-07 03:41:29 +02:00
|
|
|
.Using mp_invoke_q to invoke a list of metafunctions, technique 3
|
2017-06-10 03:44:31 +03:00
|
|
|
```
|
|
|
|
|
template<class T> using is_const_and_volatile =
|
2019-01-07 03:41:29 +02:00
|
|
|
mp_all<mp_transform<mp_invoke_q, LQ, mp_fill<LQ, T>>>;
|
2017-06-10 03:44:31 +03:00
|
|
|
```
|
2019-01-08 01:27:04 +02:00
|
|
|
|
|
|
|
|
## mp_not_fn<P>
|
|
|
|
|
|
|
|
|
|
template<template<class...> class P> struct mp_not_fn
|
|
|
|
|
{
|
|
|
|
|
template<class... T> using fn = mp_not<P<T...>>;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
`mp_not_fn<P>` returns a quoted metafunction `Q` such that `Q::fn<T...>` returns `mp_not<P<T...>>`.
|
|
|
|
|
|
|
|
|
|
That is, it negates the result of `P`.
|
|
|
|
|
|
|
|
|
|
## mp_not_fn_q<Q>
|
|
|
|
|
|
|
|
|
|
template<class Q> using mp_not_fn_q = mp_not_fn<Q::template fn>;
|
|
|
|
|
|
|
|
|
|
As `mp_not_fn`, but takes a quoted metafunction.
|