1 | #ifndef BOOST_MP11_UTILITY_HPP_INCLUDED |
2 | #define BOOST_MP11_UTILITY_HPP_INCLUDED |
3 | |
4 | // Copyright 2015-2020 Peter Dimov. |
5 | // |
6 | // Distributed under the Boost Software License, Version 1.0. |
7 | // |
8 | // See accompanying file LICENSE_1_0.txt or copy at |
9 | // http://www.boost.org/LICENSE_1_0.txt |
10 | |
11 | #include <boost/mp11/integral.hpp> |
12 | #include <boost/mp11/detail/mp_list.hpp> |
13 | #include <boost/mp11/detail/mp_fold.hpp> |
14 | #include <boost/mp11/detail/mp_front.hpp> |
15 | #include <boost/mp11/detail/mp_rename.hpp> |
16 | #include <boost/mp11/detail/mp_defer.hpp> |
17 | #include <boost/mp11/detail/config.hpp> |
18 | |
19 | namespace boost |
20 | { |
21 | namespace mp11 |
22 | { |
23 | |
24 | // mp_identity |
25 | template<class T> struct mp_identity |
26 | { |
27 | using type = T; |
28 | }; |
29 | |
30 | // mp_identity_t |
31 | template<class T> using mp_identity_t = typename mp_identity<T>::type; |
32 | |
33 | // mp_inherit |
34 | template<class... T> struct mp_inherit: T... {}; |
35 | |
36 | // mp_if, mp_if_c |
37 | // mp_valid |
38 | // mp_defer |
39 | // moved to detail/mp_defer.hpp |
40 | |
41 | // mp_eval_if, mp_eval_if_c |
42 | namespace detail |
43 | { |
44 | |
45 | template<bool C, class T, template<class...> class F, class... U> struct mp_eval_if_c_impl; |
46 | |
47 | template<class T, template<class...> class F, class... U> struct mp_eval_if_c_impl<true, T, F, U...> |
48 | { |
49 | using type = T; |
50 | }; |
51 | |
52 | template<class T, template<class...> class F, class... U> struct mp_eval_if_c_impl<false, T, F, U...>: mp_defer<F, U...> |
53 | { |
54 | }; |
55 | |
56 | } // namespace detail |
57 | |
58 | template<bool C, class T, template<class...> class F, class... U> using mp_eval_if_c = typename detail::mp_eval_if_c_impl<C, T, F, U...>::type; |
59 | template<class C, class T, template<class...> class F, class... U> using mp_eval_if = typename detail::mp_eval_if_c_impl<static_cast<bool>(C::value), T, F, U...>::type; |
60 | template<class C, class T, class Q, class... U> using mp_eval_if_q = typename detail::mp_eval_if_c_impl<static_cast<bool>(C::value), T, Q::template fn, U...>::type; |
61 | |
62 | // mp_eval_if_not |
63 | template<class C, class T, template<class...> class F, class... U> using mp_eval_if_not = mp_eval_if<mp_not<C>, T, F, U...>; |
64 | template<class C, class T, class Q, class... U> using mp_eval_if_not_q = mp_eval_if<mp_not<C>, T, Q::template fn, U...>; |
65 | |
66 | // mp_eval_or |
67 | template<class T, template<class...> class F, class... U> using mp_eval_or = mp_eval_if_not<mp_valid<F, U...>, T, F, U...>; |
68 | template<class T, class Q, class... U> using mp_eval_or_q = mp_eval_or<T, Q::template fn, U...>; |
69 | |
70 | // mp_valid_and_true |
71 | template<template<class...> class F, class... T> using mp_valid_and_true = mp_eval_or<mp_false, F, T...>; |
72 | template<class Q, class... T> using mp_valid_and_true_q = mp_valid_and_true<Q::template fn, T...>; |
73 | |
74 | // mp_cond |
75 | |
76 | // so elegant; so doesn't work |
77 | // template<class C, class T, class... E> using mp_cond = mp_eval_if<C, T, mp_cond, E...>; |
78 | |
79 | namespace detail |
80 | { |
81 | |
82 | template<class C, class T, class... E> struct mp_cond_impl; |
83 | |
84 | } // namespace detail |
85 | |
86 | template<class C, class T, class... E> using mp_cond = typename detail::mp_cond_impl<C, T, E...>::type; |
87 | |
88 | namespace detail |
89 | { |
90 | |
91 | template<class C, class T, class... E> using mp_cond_ = mp_eval_if<C, T, mp_cond, E...>; |
92 | |
93 | template<class C, class T, class... E> struct mp_cond_impl: mp_defer<mp_cond_, C, T, E...> |
94 | { |
95 | }; |
96 | |
97 | } // namespace detail |
98 | |
99 | // mp_quote |
100 | template<template<class...> class F> struct mp_quote |
101 | { |
102 | // the indirection through mp_defer works around the language inability |
103 | // to expand T... into a fixed parameter list of an alias template |
104 | |
105 | template<class... T> using fn = typename mp_defer<F, T...>::type; |
106 | }; |
107 | |
108 | // mp_quote_trait |
109 | template<template<class...> class F> struct mp_quote_trait |
110 | { |
111 | template<class... T> using fn = typename F<T...>::type; |
112 | }; |
113 | |
114 | // mp_invoke_q |
115 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1900 ) |
116 | |
117 | namespace detail |
118 | { |
119 | |
120 | template<class Q, class... T> struct mp_invoke_q_impl: mp_defer<Q::template fn, T...> {}; |
121 | |
122 | } // namespace detail |
123 | |
124 | template<class Q, class... T> using mp_invoke_q = typename detail::mp_invoke_q_impl<Q, T...>::type; |
125 | |
126 | #elif BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 50000 ) |
127 | |
128 | template<class Q, class... T> using mp_invoke_q = typename mp_defer<Q::template fn, T...>::type; |
129 | |
130 | #else |
131 | |
132 | template<class Q, class... T> using mp_invoke_q = typename Q::template fn<T...>; |
133 | |
134 | #endif |
135 | |
136 | // mp_not_fn<P> |
137 | template<template<class...> class P> struct mp_not_fn |
138 | { |
139 | template<class... T> using fn = mp_not< mp_invoke_q<mp_quote<P>, T...> >; |
140 | }; |
141 | |
142 | template<class Q> using mp_not_fn_q = mp_not_fn<Q::template fn>; |
143 | |
144 | // mp_compose |
145 | namespace detail |
146 | { |
147 | |
148 | template<class L, class Q> using mp_compose_helper = mp_list< mp_apply_q<Q, L> >; |
149 | |
150 | } // namespace detail |
151 | |
152 | #if !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1900 ) |
153 | |
154 | template<template<class...> class... F> struct mp_compose |
155 | { |
156 | template<class... T> using fn = mp_front< mp_fold<mp_list<mp_quote<F>...>, mp_list<T...>, detail::mp_compose_helper> >; |
157 | }; |
158 | |
159 | #endif |
160 | |
161 | template<class... Q> struct mp_compose_q |
162 | { |
163 | template<class... T> using fn = mp_front< mp_fold<mp_list<Q...>, mp_list<T...>, detail::mp_compose_helper> >; |
164 | }; |
165 | |
166 | } // namespace mp11 |
167 | } // namespace boost |
168 | |
169 | #endif // #ifndef BOOST_MP11_UTILITY_HPP_INCLUDED |
170 | |