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