]>
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> | |
13 | #include <boost/detail/workaround.hpp> | |
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 | |
56 | // implementation by Bruno Dutra (by the name is_evaluable) | |
57 | namespace detail | |
58 | { | |
59 | ||
60 | template<template<class...> class F, class... T> struct mp_valid_impl | |
61 | { | |
62 | template<template<class...> class G, class = G<T...>> static mp_true check(int); | |
63 | template<template<class...> class> static mp_false check(...); | |
64 | ||
65 | using type = decltype(check<F>(0)); | |
66 | }; | |
67 | ||
68 | } // namespace detail | |
69 | ||
70 | template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<F, T...>::type; | |
71 | ||
72 | // mp_defer | |
73 | namespace detail | |
74 | { | |
75 | ||
76 | template<template<class...> class F, class... T> struct mp_defer_impl | |
77 | { | |
78 | using type = F<T...>; | |
79 | }; | |
80 | ||
81 | struct mp_no_type | |
82 | { | |
83 | }; | |
84 | ||
85 | } // namespace detail | |
86 | ||
87 | 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>; | |
88 | ||
89 | // mp_eval_if, mp_eval_if_c | |
90 | namespace detail | |
91 | { | |
92 | ||
93 | template<bool C, class T, template<class...> class F, class... U> struct mp_eval_if_c_impl; | |
94 | ||
95 | template<class T, template<class...> class F, class... U> struct mp_eval_if_c_impl<true, T, F, U...> | |
96 | { | |
97 | using type = T; | |
98 | }; | |
99 | ||
100 | template<class T, template<class...> class F, class... U> struct mp_eval_if_c_impl<false, T, F, U...>: mp_defer<F, U...> | |
101 | { | |
102 | }; | |
103 | ||
104 | } // namespace detail | |
105 | ||
106 | 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; | |
107 | 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; | |
108 | 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; | |
109 | ||
110 | // mp_cond | |
111 | ||
112 | // so elegant; so doesn't work | |
113 | // template<class C, class T, class... E> using mp_cond = mp_eval_if<C, T, mp_cond, E...>; | |
114 | ||
115 | namespace detail | |
116 | { | |
117 | ||
118 | template<class C, class T, class... E> struct mp_cond_impl; | |
119 | ||
120 | } // namespace detail | |
121 | ||
122 | template<class C, class T, class... E> using mp_cond = typename detail::mp_cond_impl<C, T, E...>::type; | |
123 | ||
124 | namespace detail | |
125 | { | |
126 | ||
127 | template<class C, class T, class... E> using mp_cond_ = mp_eval_if<C, T, mp_cond, E...>; | |
128 | ||
129 | template<class C, class T, class... E> struct mp_cond_impl: mp_defer<mp_cond_, C, T, E...> | |
130 | { | |
131 | }; | |
132 | ||
133 | } // namespace detail | |
134 | ||
135 | // mp_quote | |
136 | template<template<class...> class F> struct mp_quote | |
137 | { | |
138 | // the indirection through mp_defer works around the language inability | |
139 | // to expand T... into a fixed parameter list of an alias template | |
140 | ||
141 | template<class... T> using fn = typename mp_defer<F, T...>::type; | |
142 | }; | |
143 | ||
144 | // mp_quote_trait | |
145 | template<template<class...> class F> struct mp_quote_trait | |
146 | { | |
147 | template<class... T> using fn = typename F<T...>::type; | |
148 | }; | |
149 | ||
150 | // mp_invoke | |
151 | #if BOOST_WORKAROUND( BOOST_MSVC, < 1900 ) | |
152 | ||
153 | namespace detail | |
154 | { | |
155 | ||
156 | template<class Q, class... T> struct mp_invoke_impl: mp_defer<Q::template fn, T...> {}; | |
157 | ||
158 | } // namespace detail | |
159 | ||
160 | template<class Q, class... T> using mp_invoke = typename detail::mp_invoke_impl<Q, T...>::type; | |
161 | ||
162 | #elif BOOST_WORKAROUND( BOOST_GCC, < 50000 ) | |
163 | ||
164 | template<class Q, class... T> using mp_invoke = typename mp_defer<Q::template fn, T...>::type; | |
165 | ||
166 | #else | |
167 | ||
168 | template<class Q, class... T> using mp_invoke = typename Q::template fn<T...>; | |
169 | ||
170 | #endif | |
171 | ||
172 | } // namespace mp11 | |
173 | } // namespace boost | |
174 | ||
175 | #endif // #ifndef BOOST_MP11_UTILITY_HPP_INCLUDED |