liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
#ifndef BOOST_MP11_UTILITY_HPP_INCLUDED
#define BOOST_MP11_UTILITY_HPP_INCLUDED
 
// Copyright 2015-2020 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
 
#include <boost/mp11/integral.hpp>
#include <boost/mp11/detail/mp_list.hpp>
#include <boost/mp11/detail/mp_fold.hpp>
#include <boost/mp11/detail/config.hpp>
 
namespace boost
{
namespace mp11
{
 
// mp_identity
template<class T> struct mp_identity
{
    using type = T;
};
 
// mp_identity_t
template<class T> using mp_identity_t = typename mp_identity<T>::type;
 
// mp_inherit
template<class... T> struct mp_inherit: T... {};
 
// mp_if, mp_if_c
namespace detail
{
 
template<bool C, class T, class... E> struct mp_if_c_impl
{
};
 
template<class T, class... E> struct mp_if_c_impl<true, T, E...>
{
    using type = T;
};
 
template<class T, class E> struct mp_if_c_impl<false, T, E>
{
    using type = E;
};
 
} // namespace detail
 
template<bool C, class T, class... E> using mp_if_c = typename detail::mp_if_c_impl<C, T, E...>::type;
template<class C, class T, class... E> using mp_if = typename detail::mp_if_c_impl<static_cast<bool>(C::value), T, E...>::type;
 
// mp_valid
 
#if BOOST_MP11_WORKAROUND( BOOST_MP11_INTEL, != 0 ) // tested at 1800
 
// contributed by Roland Schulz in https://github.com/boostorg/mp11/issues/17
 
namespace detail
{
 
template<class...> using void_t = void;
 
template<class, template<class...> class F, class... T>
struct mp_valid_impl: mp_false {};
 
template<template<class...> class F, class... T>
struct mp_valid_impl<void_t<F<T...>>, F, T...>: mp_true {};
 
} // namespace detail
 
template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<void, F, T...>;
 
#else
 
// implementation by Bruno Dutra (by the name is_evaluable)
namespace detail
{
 
template<template<class...> class F, class... T> struct mp_valid_impl
{
    template<template<class...> class G, class = G<T...>> static mp_true check(int);
    template<template<class...> class> static mp_false check(...);
 
    using type = decltype(check<F>(0));
};
 
} // namespace detail
 
template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<F, T...>::type;
 
#endif
 
template<class Q, class... T> using mp_valid_q = mp_valid<Q::template fn, T...>;
 
// mp_defer
namespace detail
{
 
template<template<class...> class F, class... T> struct mp_defer_impl
{
    using type = F<T...>;
};
 
struct mp_no_type
{
};
 
#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 )
 
template<template<class...> class F, class... T> struct mp_defer_cuda_workaround
{
    using type = mp_if<mp_valid<F, T...>, detail::mp_defer_impl<F, T...>, detail::mp_no_type>;
};
 
#endif
 
} // namespace detail
 
#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 )
 
template<template<class...> class F, class... T> using mp_defer = typename detail::mp_defer_cuda_workaround< F, T...>::type;
 
#else
 
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>;
 
#endif
 
// mp_eval_if, mp_eval_if_c
namespace detail
{
 
template<bool C, class T, template<class...> class F, class... U> struct mp_eval_if_c_impl;
 
template<class T, template<class...> class F, class... U> struct mp_eval_if_c_impl<true, T, F, U...>
{
    using type = T;
};
 
template<class T, template<class...> class F, class... U> struct mp_eval_if_c_impl<false, T, F, U...>: mp_defer<F, U...>
{
};
 
} // namespace detail
 
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;
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;
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;
 
// mp_eval_if_not
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...>;
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...>;
 
// mp_eval_or
template<class T, template<class...> class F, class... U> using mp_eval_or = mp_eval_if_not<mp_valid<F, U...>, T, F, U...>;
template<class T, class Q, class... U> using mp_eval_or_q = mp_eval_or<T, Q::template fn, U...>;
 
// mp_cond
 
// so elegant; so doesn't work
// template<class C, class T, class... E> using mp_cond = mp_eval_if<C, T, mp_cond, E...>;
 
namespace detail
{
 
template<class C, class T, class... E> struct mp_cond_impl;
 
} // namespace detail
 
template<class C, class T, class... E> using mp_cond = typename detail::mp_cond_impl<C, T, E...>::type;
 
namespace detail
{
 
template<class C, class T, class... E> using mp_cond_ = mp_eval_if<C, T, mp_cond, E...>;
 
template<class C, class T, class... E> struct mp_cond_impl: mp_defer<mp_cond_, C, T, E...>
{
};
 
} // namespace detail
 
// mp_quote
template<template<class...> class F> struct mp_quote
{
    // the indirection through mp_defer works around the language inability
    // to expand T... into a fixed parameter list of an alias template
 
    template<class... T> using fn = typename mp_defer<F, T...>::type;
};
 
// mp_quote_trait
template<template<class...> class F> struct mp_quote_trait
{
    template<class... T> using fn = typename F<T...>::type;
};
 
// mp_invoke_q
#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1900 )
 
namespace detail
{
 
template<class Q, class... T> struct mp_invoke_q_impl: mp_defer<Q::template fn, T...> {};
 
} // namespace detail
 
template<class Q, class... T> using mp_invoke_q = typename detail::mp_invoke_q_impl<Q, T...>::type;
 
#elif BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 50000 )
 
template<class Q, class... T> using mp_invoke_q = typename mp_defer<Q::template fn, T...>::type;
 
#else
 
template<class Q, class... T> using mp_invoke_q = typename Q::template fn<T...>;
 
#endif
 
// mp_not_fn<P>
template<template<class...> class P> struct mp_not_fn
{
    template<class... T> using fn = mp_not< mp_invoke_q<mp_quote<P>, T...> >;
};
 
template<class Q> using mp_not_fn_q = mp_not_fn<Q::template fn>;
 
// mp_compose
namespace detail
{
 
template<class T, class Q> using mp_reverse_invoke_q = mp_invoke_q<Q, T>;
 
} // namespace detail
 
#if !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1900 )
 
template<template<class...> class... F> struct mp_compose
{
    template<class T> using fn = mp_fold<mp_list<mp_quote<F>...>, T, detail::mp_reverse_invoke_q>;
};
 
#endif
 
template<class... Q> struct mp_compose_q
{
    template<class T> using fn = mp_fold<mp_list<Q...>, T, detail::mp_reverse_invoke_q>;
};
 
} // namespace mp11
} // namespace boost
 
#endif // #ifndef BOOST_MP11_UTILITY_HPP_INCLUDED