1#ifndef BOOST_MP11_DETAIL_MP_WITH_INDEX_HPP_INCLUDED
2#define BOOST_MP11_DETAIL_MP_WITH_INDEX_HPP_INCLUDED
3
4// Copyright 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/mp11/detail/config.hpp>
13#include <type_traits>
14#include <utility>
15#include <cassert>
16
17#if defined( BOOST_MP11_HAS_CXX14_CONSTEXPR )
18# define BOOST_MP11_CONSTEXPR14 constexpr
19#else
20# define BOOST_MP11_CONSTEXPR14
21#endif
22
23#if defined( __GNUC__ ) || defined( __clang__ )
24# define BOOST_MP11_UNREACHABLE_DEFAULT default: __builtin_unreachable();
25#elif defined( _MSC_VER )
26# define BOOST_MP11_UNREACHABLE_DEFAULT default: __assume(false);
27#else
28# define BOOST_MP11_UNREACHABLE_DEFAULT
29#endif
30
31namespace boost
32{
33namespace mp11
34{
35
36namespace detail
37{
38
39template<std::size_t N> struct mp_with_index_impl_
40{
41 template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
42 {
43 if( i < N / 2 )
44 {
45 return mp_with_index_impl_<N/2>::template call<K>( i, std::forward<F>(f) );
46 }
47 else
48 {
49 return mp_with_index_impl_<N-N/2>::template call<K+N/2>( i - N/2, std::forward<F>(f) );
50 }
51 }
52};
53
54template<> struct mp_with_index_impl_<0>
55{
56};
57
58template<> struct mp_with_index_impl_<1>
59{
60 template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t /*i*/, F && f )
61 {
62 return std::forward<F>(f)( mp_size_t<K+0>() );
63 }
64};
65
66template<> struct mp_with_index_impl_<2>
67{
68 template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
69 {
70 switch( i )
71 {
72 BOOST_MP11_UNREACHABLE_DEFAULT
73 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
74 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
75 }
76 }
77};
78
79template<> struct mp_with_index_impl_<3>
80{
81 template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
82 {
83 switch( i )
84 {
85 BOOST_MP11_UNREACHABLE_DEFAULT
86 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
87 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
88 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
89 }
90 }
91};
92
93template<> struct mp_with_index_impl_<4>
94{
95 template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
96 {
97 switch( i )
98 {
99 BOOST_MP11_UNREACHABLE_DEFAULT
100 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
101 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
102 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
103 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
104 }
105 }
106};
107
108template<> struct mp_with_index_impl_<5>
109{
110 template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
111 {
112 switch( i )
113 {
114 BOOST_MP11_UNREACHABLE_DEFAULT
115 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
116 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
117 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
118 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
119 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
120 }
121 }
122};
123
124template<> struct mp_with_index_impl_<6>
125{
126 template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
127 {
128 switch( i )
129 {
130 BOOST_MP11_UNREACHABLE_DEFAULT
131 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
132 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
133 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
134 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
135 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
136 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
137 }
138 }
139};
140
141template<> struct mp_with_index_impl_<7>
142{
143 template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
144 {
145 switch( i )
146 {
147 BOOST_MP11_UNREACHABLE_DEFAULT
148 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
149 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
150 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
151 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
152 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
153 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
154 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
155 }
156 }
157};
158
159template<> struct mp_with_index_impl_<8>
160{
161 template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
162 {
163 switch( i )
164 {
165 BOOST_MP11_UNREACHABLE_DEFAULT
166 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
167 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
168 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
169 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
170 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
171 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
172 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
173 case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
174 }
175 }
176};
177
178template<> struct mp_with_index_impl_<9>
179{
180 template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
181 {
182 switch( i )
183 {
184 BOOST_MP11_UNREACHABLE_DEFAULT
185 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
186 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
187 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
188 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
189 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
190 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
191 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
192 case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
193 case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
194 }
195 }
196};
197
198template<> struct mp_with_index_impl_<10>
199{
200 template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
201 {
202 switch( i )
203 {
204 BOOST_MP11_UNREACHABLE_DEFAULT
205 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
206 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
207 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
208 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
209 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
210 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
211 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
212 case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
213 case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
214 case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
215 }
216 }
217};
218
219template<> struct mp_with_index_impl_<11>
220{
221 template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
222 {
223 switch( i )
224 {
225 BOOST_MP11_UNREACHABLE_DEFAULT
226 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
227 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
228 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
229 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
230 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
231 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
232 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
233 case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
234 case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
235 case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
236 case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
237 }
238 }
239};
240
241template<> struct mp_with_index_impl_<12>
242{
243 template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
244 {
245 switch( i )
246 {
247 BOOST_MP11_UNREACHABLE_DEFAULT
248 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
249 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
250 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
251 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
252 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
253 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
254 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
255 case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
256 case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
257 case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
258 case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
259 case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
260 }
261 }
262};
263
264template<> struct mp_with_index_impl_<13>
265{
266 template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
267 {
268 switch( i )
269 {
270 BOOST_MP11_UNREACHABLE_DEFAULT
271 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
272 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
273 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
274 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
275 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
276 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
277 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
278 case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
279 case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
280 case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
281 case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
282 case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
283 case 12: return std::forward<F>(f)( mp_size_t<K+12>() );
284 }
285 }
286};
287
288template<> struct mp_with_index_impl_<14>
289{
290 template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
291 {
292 switch( i )
293 {
294 BOOST_MP11_UNREACHABLE_DEFAULT
295 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
296 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
297 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
298 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
299 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
300 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
301 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
302 case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
303 case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
304 case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
305 case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
306 case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
307 case 12: return std::forward<F>(f)( mp_size_t<K+12>() );
308 case 13: return std::forward<F>(f)( mp_size_t<K+13>() );
309 }
310 }
311};
312
313template<> struct mp_with_index_impl_<15>
314{
315 template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
316 {
317 switch( i )
318 {
319 BOOST_MP11_UNREACHABLE_DEFAULT
320 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
321 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
322 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
323 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
324 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
325 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
326 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
327 case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
328 case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
329 case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
330 case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
331 case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
332 case 12: return std::forward<F>(f)( mp_size_t<K+12>() );
333 case 13: return std::forward<F>(f)( mp_size_t<K+13>() );
334 case 14: return std::forward<F>(f)( mp_size_t<K+14>() );
335 }
336 }
337};
338
339template<> struct mp_with_index_impl_<16>
340{
341 template<std::size_t K, class F> static BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) call( std::size_t i, F && f )
342 {
343 switch( i )
344 {
345 BOOST_MP11_UNREACHABLE_DEFAULT
346 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
347 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
348 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
349 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
350 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
351 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
352 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
353 case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
354 case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
355 case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
356 case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
357 case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
358 case 12: return std::forward<F>(f)( mp_size_t<K+12>() );
359 case 13: return std::forward<F>(f)( mp_size_t<K+13>() );
360 case 14: return std::forward<F>(f)( mp_size_t<K+14>() );
361 case 15: return std::forward<F>(f)( mp_size_t<K+15>() );
362 }
363 }
364};
365
366} // namespace detail
367
368template<std::size_t N, class F> inline BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) mp_with_index( std::size_t i, F && f )
369{
370 assert( i < N );
371 return detail::mp_with_index_impl_<N>::template call<0>( i, std::forward<F>(f) );
372}
373
374template<class N, class F> inline BOOST_MP11_CONSTEXPR14 decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) mp_with_index( std::size_t i, F && f )
375{
376 return mp_with_index<std::size_t{N::value}>( i, std::forward<F>(f) );
377}
378
379#undef BOOST_MP11_CONSTEXPR14
380#undef BOOST_MP11_UNREACHABLE_DEFAULT
381
382} // namespace mp11
383} // namespace boost
384
385#endif // #ifndef BOOST_MP11_DETAIL_MP_WITH_INDEX_HPP_INCLUDED
386

source code of include/boost/mp11/detail/mp_with_index.hpp