forked from boostorg/mp11
153 lines
4.7 KiB
Plaintext
153 lines
4.7 KiB
Plaintext
////
|
|
Copyright 2017 Peter Dimov
|
|
|
|
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
|
|
////
|
|
|
|
[#function]
|
|
# Helper Metafunctions, <boost/mp11/function.hpp>
|
|
:toc:
|
|
:toc-title:
|
|
:idprefix:
|
|
|
|
## mp_void<T...>
|
|
|
|
template<class... T> using mp_void = void;
|
|
|
|
Same as `std::void_t` from C++17.
|
|
|
|
## mp_and<T...>
|
|
|
|
template<class... T> using mp_and = /*...*/;
|
|
|
|
`mp_and<T...>` applies `mp_to_bool` to the types in `T...`, in order. If the result of an application is `mp_false`, `mp_and`
|
|
returns `mp_false`. If the application causes a substitution failure, returns `mp_false`. If all results are `mp_true`,
|
|
returns `mp_true`. `mp_and<>` is `mp_true`.
|
|
|
|
.mp_and behavior
|
|
```
|
|
using R1 = mp_and<mp_true, mp_true>; // mp_true
|
|
|
|
using R2 = mp_and<mp_false, void>; // mp_false, void is not reached
|
|
|
|
using R3 = mp_and<mp_false, mp_false>; // mp_false
|
|
|
|
using R4 = mp_and<void, mp_true>; // mp_false (!)
|
|
```
|
|
|
|
## mp_all<T...>
|
|
|
|
template<class... T> using mp_all = /*...*/;
|
|
|
|
`mp_all<T...>` is `mp_true` if `mp_to_bool<U>` is `mp_true` for all types `U` in `T...`, `mp_false` otherwise. Same as
|
|
`mp_and`, but does not perform short-circuit evaluation. `mp_and<mp_false, void>` is `mp_false`, but `mp_all<mp_false, void>`
|
|
is an error because `void` does not have a nested `value`. The upside is that `mp_all` is potentially faster and does not
|
|
mask substitution failures as `mp_and` does.
|
|
|
|
.mp_all behavior
|
|
```
|
|
using R1 = mp_all<mp_true, mp_true>; // mp_true
|
|
|
|
using R2 = mp_all<mp_false, void>; // compile-time error
|
|
|
|
using R3 = mp_all<mp_false, mp_false>; // mp_false
|
|
|
|
using R4 = mp_all<void, mp_true>; // compile-time error
|
|
```
|
|
|
|
## mp_or<T...>
|
|
|
|
template<class... T> using mp_or = /*...*/;
|
|
|
|
`mp_or<T...>` applies `mp_to_bool` to the types in `T...`, in order. If the result of an application is `mp_true`, `mp_or`
|
|
returns `mp_true`. If all results are `mp_false`, returns `mp_false`. `mp_or<>` is `mp_false`.
|
|
|
|
.mp_or behavior
|
|
```
|
|
using R1 = mp_or<mp_true, mp_false>; // mp_true
|
|
|
|
using R2 = mp_or<mp_true, void>; // mp_true, void is not reached
|
|
|
|
using R3 = mp_or<mp_false, mp_false>; // mp_false
|
|
|
|
using R4 = mp_or<void, mp_true>; // compile-time error
|
|
```
|
|
|
|
## mp_any<T...>
|
|
|
|
template<class... T> using mp_any = /*...*/;
|
|
|
|
`mp_any<T...>` is `mp_true` if `mp_to_bool<U>` is `mp_true` for any type `U` in `T...`, `mp_false` otherwise. Same as
|
|
`mp_or`, but does not perform short-circuit evaluation.
|
|
|
|
.mp_any behavior
|
|
```
|
|
using R1 = mp_any<mp_true, mp_false>; // mp_true
|
|
|
|
using R2 = mp_any<mp_true, void>; // compile-time error
|
|
|
|
using R3 = mp_any<mp_false, mp_false>; // mp_false
|
|
|
|
using R4 = mp_any<void, mp_true>; // compile-time error
|
|
```
|
|
|
|
## mp_same<T...>
|
|
|
|
template<class... T> using mp_same = /*...*/;
|
|
|
|
`mp_same<T...>` is `mp_true` if all the types in `T...` are the same type, `mp_false` otherwise. `mp_same<>` is `mp_true`.
|
|
|
|
## mp_similar<T...>
|
|
|
|
template<class... T> using mp_similar = /*...*/;
|
|
|
|
`mp_similar<T...>` is `mp_true` if all the types in `T...` are the same type, or instantiations of the same class template
|
|
whose parameters are all types, `mp_false` otherwise. `mp_similar<>` is `mp_true`.
|
|
|
|
.mp_similar
|
|
```
|
|
using R1 = mp_similar<void>; // mp_true
|
|
using R2 = mp_similar<void, void>; // mp_true
|
|
using R3 = mp_similar<void, void, void>; // mp_true
|
|
using R4 = mp_similar<void, void, float>; // mp_false
|
|
|
|
template<class T> struct X;
|
|
template<class... T> struct Y;
|
|
|
|
using R5 = mp_similar<X<int>, X<void>, X<float>>; // mp_true
|
|
using R6 = mp_similar<Y<>, Y<void>, Y<void, void>>; // mp_true
|
|
using R7 = mp_similar<X<void>, Y<void>>; // mp_false
|
|
```
|
|
|
|
## mp_plus<T...>
|
|
|
|
template<class... T> using mp_plus = /*...*/;
|
|
|
|
`mp_plus<T...>` is an integral constant type with a value that is the sum of `U::value` for all types `U` in `T...`.
|
|
`mp_plus<>` is `mp_int<0>`.
|
|
|
|
## mp_less<T1, T2>
|
|
|
|
template<class T1, class T2> using mp_less = /*...*/;
|
|
|
|
`mp_less<T1, T2>` is `mp_true` when the numeric value of `T1::value` is less than the numeric value of `T2::value`,
|
|
`mp_false` otherwise.
|
|
|
|
(Note that this is not necessarily the same as `T1::value < T2::value` when comparing between signed and unsigned types;
|
|
`-1 < 1u` is `false`, but `mp_less<mp_int\<-1>, mp_size_t<1>>` is `mp_true`.)
|
|
|
|
## mp_min<T1, T...>
|
|
|
|
template<class T1, class... T> using mp_min = mp_min_element<mp_list<T1, T...>, mp_less>;
|
|
|
|
`mp_min<T...>` returns the type `U` in `T...` with the lowest `U::value`.
|
|
|
|
## mp_max<T1, T...>
|
|
|
|
template<class T1, class... T> using mp_max = mp_max_element<mp_list<T1, T...>, mp_less>;
|
|
|
|
`mp_max<T...>` returns the type `U` in `T...` with the highest `U::value`.
|