//// Copyright 2017, 2019 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 //// [#utility] # Utility Components, :toc: :toc-title: :idprefix: ## mp_identity template struct mp_identity { using type = T; }; `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 for passing types as values to functions. .Using mp_identity as a type trait ``` template using addp_if_not_ref = typename mp_if, mp_identity, std::add_pointer>::type; ``` .Using mp_identity to protect qualifiers and references ``` template void print1() { std::cout << typeid(T).name() << std::endl; } template void print2() { std::cout << typeid(mp_identity).name() << std::endl; } int main() { print1(); // 'int' print2(); // 'mp_identity' } ``` ## mp_identity_t template using mp_identity_t = typename mp_identity::type; ## mp_inherit template struct mp_inherit: T... {}; ## mp_if_c template using mp_if_c = /*...*/; `mp_if_c` is an alias for `T`. `mp_if_c` is an alias for `E`. Otherwise, the result is a substitution failure. .Using mp_if_c to select between two alternatives ``` using R1 = mp_if_c; // int using R2 = mp_if_c; // void ``` .Using mp_if_c to fail substitution when a condition is not met ``` template using void_if_5 = mp_if_c; ``` This example returns `void` when `I::value` is 5, and generates a substitution failure otherwise. It's the same as `std::enable_if_t` in {cpp}14, or `typename std::enable_if::type` in {cpp}11. ## mp_if template using mp_if = mp_if_c(C::value), T, E...>; Like `mp_if_c`, but the first argument is a type. .Using mp_if to select between two alternatives ``` using R1 = mp_if; // int using R2 = mp_if; // void ``` .Using mp_if to fail substitution when a condition is not met ``` template using void_if_const = mp_if, void>; template using void_if_all_const = mp_if...>, void>; template using if_non_const = mp_if>, T>; ``` ## mp_eval_if_c template class F, class... U> using mp_eval_if_c = /*...*/; `mp_eval_if_c` is an alias for `T` when `C` is `true`, for `F` otherwise. Its purpose is to avoid evaluating `F` when the condition is `true` as it may not be valid in this case. .Using mp_eval_if_c to select the first pack element, or void ``` template using first_or_void = mp_eval_if_c>; ``` ## mp_eval_if template class F, class... U> using mp_eval_if = mp_eval_if_c(C::value), T, F, U...>; Like `mp_eval_if_c`, but the first argument is a type. .Using mp_eval_if to select the first list element, or void ``` template using first_or_void = mp_eval_if, void, mp_first, L>; ``` ## mp_eval_if_q template using mp_eval_if_q = mp_eval_if; Like `mp_eval_if`, but takes a quoted metafunction. ## mp_eval_if_not template class F, class... U> using mp_eval_if_not = mp_eval_if, T, F, U...>; Same as `mp_eval_if`, but the condition is reversed. ## mp_eval_if_not_q template using mp_eval_if_not_q = mp_eval_if_not; Same as `mp_eval_if_not`, but takes a quoted metafunction. ## mp_valid template class F, class... T> using mp_valid = /*...*/; `mp_valid` is an alias for `mp_true` when `F` 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 using get_nested_type = typename T::type; template struct has_nested_type: mp_valid {}; ``` ## mp_valid_q template using mp_valid_q = mp_valid; Like `mp_valid`, but takes a quoted metafunction. ## mp_eval_or template class F, class... U> using mp_eval_or = mp_eval_if_not, T, F, U...>; `mp_eval_or` is an alias for `F` when this expression is valid, for `T` otherwise. .Using mp_eval_or to select the first pack element, or void ``` template using first_or_void = mp_eval_or>; ``` ## mp_eval_or_q template using mp_eval_or_q = mp_eval_or; Like `mp_eval_or`, but takes a quoted metafunction. ## mp_cond template using mp_cond = /*...*/; `mp_cond` is an alias for `T` when `static_cast(C::value)` is `true`. When `static_cast(C::value)` is `false`, it's an alias for `mp_cond`. (If `static_cast(C::value)` is a substitution failure, the result is too a substitution failure.) .Using mp_cond ``` template using unsigned_ = mp_cond< mp_bool, uint8_t, mp_bool, uint16_t, mp_bool, uint32_t, mp_bool, uint64_t, mp_true, unsigned // default case >; ``` ## mp_defer template class F, class... T> using mp_defer = /*...*/; When `mp_valid` is `mp_true`, `mp_defer` is a struct with a nested type `type` which is an alias for `F`. Otherwise, `mp_defer` is an empty struct. ## mp_quote template class F> struct mp_quote { template using fn = F; }; `mp_quote` transforms the template `F` into a _quoted metafunction_, a type with a nested template `fn` such that `fn` returns `F`. .Using mp_quote to make a list of metafunctions ``` using LQ = mp_list, mp_quote>; ``` ## mp_quote_trait template class F> struct mp_quote_trait { template using fn = typename F::type; }; `mp_quote_trait` transforms the C++03-style trait `F` into a quoted metafunction. .Using mp_quote_trait with std::add_pointer ``` using L1 = mp_list; using R1 = mp_transform_q, L1>; // mp_list ``` ## mp_invoke_q template using mp_invoke_q = typename Q::template fn; `mp_invoke_q` evaluates the nested template `fn` of a quoted metafunction. `mp_invoke_q, T...>` returns `F`. .Using mp_invoke_q to invoke a list of metafunctions, technique 1 ``` using LQ = mp_list, mp_quote>; template using is_const_and_volatile = mp_apply>>; ``` .Using mp_invoke_q to invoke a list of metafunctions, technique 2 ``` template using is_const_and_volatile = mp_apply, LQ>>; ``` .Using mp_invoke_q to invoke a list of metafunctions, technique 3 ``` template using is_const_and_volatile = mp_apply>>; ``` ## mp_not_fn

template class P> struct mp_not_fn { template using fn = mp_not>; }; `mp_not_fn

` returns a quoted metafunction `Q` such that `Q::fn` returns `mp_not>`. That is, it negates the result of `P`. ## mp_not_fn_q template using mp_not_fn_q = mp_not_fn; As `mp_not_fn`, but takes a quoted metafunction.