1////
2Copyright 2017, 2019 Peter Dimov
3
4Distributed under the Boost Software License, Version 1.0.
5
6See accompanying file LICENSE_1_0.txt or copy at
7http://www.boost.org/LICENSE_1_0.txt
8////
9
10[#utility]
11# Utility Components, <boost/mp11/utility.hpp>
12:toc:
13:toc-title:
14:idprefix:
15
16## mp_identity<T>
17
18    template<class T> struct mp_identity
19    {
20        using type = T;
21    };
22
23`mp_identity` is a simple _transformation type trait_ (as per the C++ standard)
24that just returns the same type. It's useful both as such, and as a type wrapper
25for passing types as values to functions.
26
27.Using mp_identity as a type trait
28```
29template<class T> using addp_if_not_ref =
30    typename mp_if<std::is_reference<T>, mp_identity<T>, std::add_pointer<T>>::type;
31```
32
33.Using mp_identity to protect qualifiers and references
34```
35template<class T> void print1()
36{
37    std::cout << typeid(T).name() << std::endl;
38}
39
40template<class T> void print2()
41{
42    std::cout << typeid(mp_identity<T>).name() << std::endl;
43}
44
45int main()
46{
47    print1<int const&>(); // 'int'
48    print2<int const&>(); // 'mp_identity<int const &>'
49}
50```
51
52## mp_identity_t<T>
53
54    template<class T> using mp_identity_t = typename mp_identity<T>::type;
55
56## mp_inherit<T...>
57
58    template<class... T> struct mp_inherit: T... {};
59
60## mp_if_c<C, T, E...>
61
62    template<bool C, class T, class... E> using mp_if_c = /*...*/;
63
64`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.
65
66.Using mp_if_c to select between two alternatives
67```
68using R1 = mp_if_c<true, int, void>;  // int
69
70using R2 = mp_if_c<false, int, void>; // void
71```
72
73.Using mp_if_c to fail substitution when a condition is not met
74```
75template<class I> using void_if_5 = mp_if_c<I::value == 5, void>;
76```
77This example returns `void` when `I::value` is 5, and generates a substitution failure
78otherwise. It's the same as `std::enable_if_t<I::value == 5>` in {cpp}14, or
79`typename std::enable_if<I::value == 5>::type` in {cpp}11.
80
81## mp_if<C, T, E...>
82
83    template<class C, class T, class... E> using mp_if =
84        mp_if_c<static_cast<bool>(C::value), T, E...>;
85
86Like `mp_if_c`, but the first argument is a type.
87
88.Using mp_if to select between two alternatives
89```
90using R1 = mp_if<mp_true, int, void>;  // int
91
92using R2 = mp_if<mp_false, int, void>; // void
93```
94
95.Using mp_if to fail substitution when a condition is not met
96```
97template<class T> using void_if_const = mp_if<std::is_const<T>, void>;
98
99template<class... T> using void_if_all_const =
100    mp_if<mp_all<std::is_const<T>...>, void>;
101
102template<class T> using if_non_const = mp_if<mp_not<std::is_const<T>>, T>;
103```
104
105## mp_eval_if_c<C, T, F, U...>
106
107    template<bool C, class T, template<class...> class F, class... U> using mp_eval_if_c =
108        /*...*/;
109
110`mp_eval_if_c<C, T, F, U...>` is an alias for `T` when `C` is `true`, for `F<U...>` otherwise. Its purpose
111is to avoid evaluating `F<U...>` when the condition is `true` as it may not be valid in this case.
112
113.Using mp_eval_if_c to select the first pack element, or void
114```
115template<class... T> using first_or_void =
116    mp_eval_if_c<sizeof...(T) == 0, void, mp_apply, mp_first, mp_list<T...>>;
117```
118
119## mp_eval_if<C, T, F, U...>
120
121    template<class C, class T, template<class...> class F, class... U> using mp_eval_if =
122        mp_eval_if_c<static_cast<bool>(C::value), T, F, U...>;
123
124Like `mp_eval_if_c`, but the first argument is a type.
125
126.Using mp_eval_if to select the first list element, or void
127```
128template<class L> using first_or_void = mp_eval_if<mp_empty<L>, void, mp_first, L>;
129```
130
131## mp_eval_if_q<C, T, Q, U...>
132
133    template<class C, class T, class Q, class... U> using mp_eval_if_q =
134        mp_eval_if<C, T, Q::template fn, U...>;
135
136Like `mp_eval_if`, but takes a quoted metafunction.
137
138## mp_eval_if_not<C, T, F, U...>
139
140    template<class C, class T, template<class...> class F, class... U>
141        using mp_eval_if_not = mp_eval_if<mp_not<C>, T, F, U...>;
142
143Same as `mp_eval_if`, but the condition is reversed.
144
145## mp_eval_if_not_q<C, T, Q, U...>
146
147    template<class C, class T, class Q, class... U> using mp_eval_if_not_q =
148        mp_eval_if_not<C, T, Q::template fn, U...>;
149
150Same as `mp_eval_if_not`, but takes a quoted metafunction.
151
152## mp_valid<F, T...>
153
154    template<template<class...> class F, class... T> using mp_valid = /*...*/;
155
156`mp_valid<F, T...>` is an alias for `mp_true` when `F<T...>` is a valid expression, for `mp_false` otherwise.
157
158.Using mp_valid to write a metafunction that checks for the existence of a nested type
159```
160template<class T> using get_nested_type = typename T::type;
161
162template<class T> struct has_nested_type: mp_valid<get_nested_type, T> {};
163```
164
165## mp_valid_q<Q, T...>
166
167    template<class Q, class... T> using mp_valid_q = mp_valid<Q::template fn, T...>;
168
169Like `mp_valid`, but takes a quoted metafunction.
170
171## mp_eval_or<T, F, U...>
172
173    template<class T, template<class...> class F, class... U> using mp_eval_or =
174        mp_eval_if_not<mp_valid<F, U...>, T, F, U...>;
175
176`mp_eval_or<T, F, U...>` is an alias for `F<U...>` when this expression is valid, for `T` otherwise.
177
178## mp_eval_or_q<T, Q, U...>
179
180    template<class T, class Q, class... U> using mp_eval_or_q =
181        mp_eval_or<T, Q::template fn, U...>;
182
183Like `mp_eval_or`, but takes a quoted metafunction.
184
185## mp_cond<C, T, R...>
186
187    template<class C, class T, class... R> using mp_cond = /*...*/;
188
189`mp_cond<C, T, R...>` is an alias for `T` when `static_cast<bool>(C::value)` is `true`.
190When `static_cast<bool>(C::value)` is `false`, it's an alias for `mp_cond<R...>`.
191
192(If `static_cast<bool>(C::value)` is a substitution failure, the result is too a substitution
193failure.)
194
195.Using mp_cond
196```
197template<int N> using unsigned_ = mp_cond<
198    mp_bool<N ==  8>, uint8_t,
199    mp_bool<N == 16>, uint16_t,
200    mp_bool<N == 32>, uint32_t,
201    mp_bool<N == 64>, uint64_t,
202    mp_true, unsigned // default case
203>;
204```
205
206## mp_defer<F, T...>
207
208    template<template<class...> class F, class... T> using mp_defer = /*...*/;
209
210When `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,
211`mp_defer<F, T...>` is an empty struct.
212
213## mp_quote<F>
214
215    template<template<class...> class F> struct mp_quote
216    {
217        template<class... T> using fn = F<T...>;
218    };
219
220`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...>`.
221
222.Using mp_quote to make a list of metafunctions
223```
224using LQ = mp_list<mp_quote<std::is_const>, mp_quote<std::is_volatile>>;
225```
226
227## mp_quote_trait<F>
228
229    template<template<class...> class F> struct mp_quote_trait
230    {
231        template<class... T> using fn = typename F<T...>::type;
232    };
233
234`mp_quote_trait<F>` transforms the C++03-style trait `F` into a quoted metafunction.
235
236.Using mp_quote_trait with std::add_pointer
237```
238using L1 = mp_list<int, void, float>;
239using R1 = mp_transform_q<mp_quote_trait<std::add_pointer>, L1>;
240  // mp_list<int*, void*, float*>
241```
242
243## mp_invoke_q<Q, T...>
244
245    template<class Q, class... T> using mp_invoke_q = typename Q::template fn<T...>;
246
247`mp_invoke_q<Q, T...>` evaluates the nested template `fn` of a quoted metafunction. `mp_invoke_q<mp_quote<F>, T...>` returns `F<T...>`.
248
249.Using mp_invoke_q to invoke a list of metafunctions, technique 1
250```
251using LQ = mp_list<mp_quote<std::is_const>, mp_quote<std::is_volatile>>;
252
253template<class T> using is_const_and_volatile =
254    mp_all<mp_product<mp_invoke_q, LQ, mp_list<T>>>;
255```
256
257.Using mp_invoke_q to invoke a list of metafunctions, technique 2
258```
259template<class T> using is_const_and_volatile =
260    mp_all<mp_transform_q<mp_bind_back<mp_invoke_q, T>, LQ>>;
261```
262
263.Using mp_invoke_q to invoke a list of metafunctions, technique 3
264```
265template<class T> using is_const_and_volatile =
266    mp_all<mp_transform<mp_invoke_q, LQ, mp_fill<LQ, T>>>;
267```
268
269## mp_not_fn<P>
270
271    template<template<class...> class P> struct mp_not_fn
272    {
273        template<class... T> using fn = mp_not<P<T...>>;
274    };
275
276`mp_not_fn<P>` returns a quoted metafunction `Q` such that `Q::fn<T...>` returns `mp_not<P<T...>>`.
277
278That is, it negates the result of `P`.
279
280## mp_not_fn_q<Q>
281
282    template<class Q> using mp_not_fn_q = mp_not_fn<Q::template fn>;
283
284As `mp_not_fn`, but takes a quoted metafunction.
285