]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | #ifndef BOOST_MP11_UTILITY_HPP_INCLUDED |
2 | #define BOOST_MP11_UTILITY_HPP_INCLUDED | |
3 | ||
4 | // Copyright 2015, 2017 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/config.hpp> | |
11fdf7f2 | 13 | #include <boost/config/workaround.hpp> |
b32b8144 FG |
14 | |
15 | namespace boost | |
16 | { | |
17 | namespace mp11 | |
18 | { | |
19 | ||
20 | // mp_identity | |
21 | template<class T> struct mp_identity | |
22 | { | |
23 | using type = T; | |
24 | }; | |
25 | ||
26 | // mp_identity_t | |
27 | template<class T> using mp_identity_t = typename mp_identity<T>::type; | |
28 | ||
29 | // mp_inherit | |
30 | template<class... T> struct mp_inherit: T... {}; | |
31 | ||
32 | // mp_if, mp_if_c | |
33 | namespace detail | |
34 | { | |
35 | ||
36 | template<bool C, class T, class... E> struct mp_if_c_impl | |
37 | { | |
38 | }; | |
39 | ||
40 | template<class T, class... E> struct mp_if_c_impl<true, T, E...> | |
41 | { | |
42 | using type = T; | |
43 | }; | |
44 | ||
45 | template<class T, class E> struct mp_if_c_impl<false, T, E> | |
46 | { | |
47 | using type = E; | |
48 | }; | |
49 | ||
50 | } // namespace detail | |
51 | ||
52 | template<bool C, class T, class... E> using mp_if_c = typename detail::mp_if_c_impl<C, T, E...>::type; | |
53 | template<class C, class T, class... E> using mp_if = typename detail::mp_if_c_impl<static_cast<bool>(C::value), T, E...>::type; | |
54 | ||
55 | // mp_valid | |
11fdf7f2 TL |
56 | |
57 | #if BOOST_WORKAROUND(BOOST_INTEL, BOOST_TESTED_AT(1800)) | |
58 | ||
59 | // contributed by Roland Schulz in https://github.com/boostorg/mp11/issues/17 | |
60 | ||
61 | namespace detail | |
62 | { | |
63 | ||
64 | template<class...> using void_t = void; | |
65 | ||
66 | template<class, template<class...> class F, class... T> | |
67 | struct mp_valid_impl: mp_false {}; | |
68 | ||
69 | template<template<class...> class F, class... T> | |
70 | struct mp_valid_impl<void_t<F<T...>>, F, T...>: mp_true {}; | |
71 | ||
72 | } // namespace detail | |
73 | ||
74 | template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<void, F, T...>; | |
75 | ||
76 | #else | |
77 | ||
b32b8144 FG |
78 | // implementation by Bruno Dutra (by the name is_evaluable) |
79 | namespace detail | |
80 | { | |
81 | ||
82 | template<template<class...> class F, class... T> struct mp_valid_impl | |
83 | { | |
84 | template<template<class...> class G, class = G<T...>> static mp_true check(int); | |
85 | template<template<class...> class> static mp_false check(...); | |
86 | ||
87 | using type = decltype(check<F>(0)); | |
88 | }; | |
89 | ||
90 | } // namespace detail | |
91 | ||
92 | template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<F, T...>::type; | |
93 | ||
11fdf7f2 TL |
94 | #endif |
95 | ||
b32b8144 FG |
96 | // mp_defer |
97 | namespace detail | |
98 | { | |
99 | ||
100 | template<template<class...> class F, class... T> struct mp_defer_impl | |
101 | { | |
102 | using type = F<T...>; | |
103 | }; | |
104 | ||
105 | struct mp_no_type | |
106 | { | |
107 | }; | |
108 | ||
109 | } // namespace detail | |
110 | ||
111 | template<template<class...> class F, class... T> using mp_defer = mp_if<mp_valid<F, T...>, detail::mp_defer_impl<F, T...>, detail::mp_no_type>; | |
112 | ||
113 | // mp_eval_if, mp_eval_if_c | |
114 | namespace detail | |
115 | { | |
116 | ||
117 | template<bool C, class T, template<class...> class F, class... U> struct mp_eval_if_c_impl; | |
118 | ||
119 | template<class T, template<class...> class F, class... U> struct mp_eval_if_c_impl<true, T, F, U...> | |
120 | { | |
121 | using type = T; | |
122 | }; | |
123 | ||
124 | template<class T, template<class...> class F, class... U> struct mp_eval_if_c_impl<false, T, F, U...>: mp_defer<F, U...> | |
125 | { | |
126 | }; | |
127 | ||
128 | } // namespace detail | |
129 | ||
130 | 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; | |
131 | 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; | |
132 | 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; | |
133 | ||
134 | // mp_cond | |
135 | ||
136 | // so elegant; so doesn't work | |
137 | // template<class C, class T, class... E> using mp_cond = mp_eval_if<C, T, mp_cond, E...>; | |
138 | ||
139 | namespace detail | |
140 | { | |
141 | ||
142 | template<class C, class T, class... E> struct mp_cond_impl; | |
143 | ||
144 | } // namespace detail | |
145 | ||
146 | template<class C, class T, class... E> using mp_cond = typename detail::mp_cond_impl<C, T, E...>::type; | |
147 | ||
148 | namespace detail | |
149 | { | |
150 | ||
151 | template<class C, class T, class... E> using mp_cond_ = mp_eval_if<C, T, mp_cond, E...>; | |
152 | ||
153 | template<class C, class T, class... E> struct mp_cond_impl: mp_defer<mp_cond_, C, T, E...> | |
154 | { | |
155 | }; | |
156 | ||
157 | } // namespace detail | |
158 | ||
159 | // mp_quote | |
160 | template<template<class...> class F> struct mp_quote | |
161 | { | |
162 | // the indirection through mp_defer works around the language inability | |
163 | // to expand T... into a fixed parameter list of an alias template | |
164 | ||
165 | template<class... T> using fn = typename mp_defer<F, T...>::type; | |
166 | }; | |
167 | ||
168 | // mp_quote_trait | |
169 | template<template<class...> class F> struct mp_quote_trait | |
170 | { | |
171 | template<class... T> using fn = typename F<T...>::type; | |
172 | }; | |
173 | ||
174 | // mp_invoke | |
175 | #if BOOST_WORKAROUND( BOOST_MSVC, < 1900 ) | |
176 | ||
177 | namespace detail | |
178 | { | |
179 | ||
180 | template<class Q, class... T> struct mp_invoke_impl: mp_defer<Q::template fn, T...> {}; | |
181 | ||
182 | } // namespace detail | |
183 | ||
184 | template<class Q, class... T> using mp_invoke = typename detail::mp_invoke_impl<Q, T...>::type; | |
185 | ||
186 | #elif BOOST_WORKAROUND( BOOST_GCC, < 50000 ) | |
187 | ||
188 | template<class Q, class... T> using mp_invoke = typename mp_defer<Q::template fn, T...>::type; | |
189 | ||
190 | #else | |
191 | ||
192 | template<class Q, class... T> using mp_invoke = typename Q::template fn<T...>; | |
193 | ||
194 | #endif | |
195 | ||
196 | } // namespace mp11 | |
197 | } // namespace boost | |
198 | ||
199 | #endif // #ifndef BOOST_MP11_UTILITY_HPP_INCLUDED |