//// 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, :toc: :toc-title: :idprefix: ## mp_void template using mp_void = void; Same as `std::void_t` from C++17. ## mp_and template using mp_and = /*...*/; `mp_and` 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 using R2 = mp_and; // mp_false, void is not reached using R3 = mp_and; // mp_false using R4 = mp_and; // mp_false (!) ``` ## mp_all template using mp_all = /*...*/; `mp_all` is `mp_true` if `mp_to_bool` 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` is `mp_false`, but `mp_all` 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 using R2 = mp_all; // compile-time error using R3 = mp_all; // mp_false using R4 = mp_all; // compile-time error ``` ## mp_or template using mp_or = /*...*/; `mp_or` 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 using R2 = mp_or; // mp_true, void is not reached using R3 = mp_or; // mp_false using R4 = mp_or; // compile-time error ``` ## mp_any template using mp_any = /*...*/; `mp_any` is `mp_true` if `mp_to_bool` 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 using R2 = mp_any; // compile-time error using R3 = mp_any; // mp_false using R4 = mp_any; // compile-time error ``` ## mp_same template using mp_same = /*...*/; `mp_same` is `mp_true` if all the types in `T...` are the same type, `mp_false` otherwise. `mp_same<>` is `mp_true`. ## mp_plus template using mp_plus = /*...*/; `mp_plus` 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 template using mp_less = /*...*/; `mp_less` 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_size_t<1>>` is `mp_true`.) ## mp_min template using mp_min = mp_min_element, mp_less>; `mp_min` returns the type `U` in `T...` with the lowest `U::value`. ## mp_max template using mp_max = mp_max_element, mp_less>; `mp_max` returns the type `U` in `T...` with the highest `U::value`.