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