1 #ifndef BOOST_MP11_DETAIL_MP_WITH_INDEX_HPP_INCLUDED
2 #define BOOST_MP11_DETAIL_MP_WITH_INDEX_HPP_INCLUDED
4 // Copyright 2017 Peter Dimov.
6 // Distributed under the Boost Software License, Version 1.0.
8 // See accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt
11 #include <boost/mp11/integral.hpp>
12 #include <boost/mp11/detail/config.hpp>
13 #include <type_traits>
17 #if defined( BOOST_MP11_HAS_CXX14_CONSTEXPR )
18 # define BOOST_MP11_CONSTEXPR14 constexpr
20 # define BOOST_MP11_CONSTEXPR14
23 #if defined( _MSC_VER ) && !defined( __clang__ )
24 # define BOOST_MP11_UNREACHABLE() __assume(false)
26 # define BOOST_MP11_UNREACHABLE() __builtin_unreachable()
37 template<std::size_t N> struct 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 )
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>() );
61 return mp_with_index_impl_<N-16>::template call<K+16>( i-16, std::forward<F>(f) );
65 template<> struct mp_with_index_impl_<0>
69 template<> struct mp_with_index_impl_<1>
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 )
73 return std::forward<F>(f)( mp_size_t<K+0>() );
77 template<> struct mp_with_index_impl_<2>
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 )
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>() );
90 template<> struct mp_with_index_impl_<3>
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 )
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>() );
104 template<> struct mp_with_index_impl_<4>
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 )
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>() );
119 template<> struct mp_with_index_impl_<5>
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 )
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>() );
135 template<> struct mp_with_index_impl_<6>
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 )
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>() );
152 template<> struct mp_with_index_impl_<7>
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 )
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>() );
170 template<> struct mp_with_index_impl_<8>
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 )
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>() );
189 template<> struct mp_with_index_impl_<9>
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 )
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>() );
209 template<> struct mp_with_index_impl_<10>
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 )
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>() );
230 template<> struct mp_with_index_impl_<11>
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 )
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>() );
252 template<> struct mp_with_index_impl_<12>
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 )
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>() );
275 template<> struct mp_with_index_impl_<13>
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 )
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>() );
299 template<> struct mp_with_index_impl_<14>
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 )
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>() );
324 template<> struct mp_with_index_impl_<15>
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 )
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>() );
350 template<> struct mp_with_index_impl_<16>
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 )
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>() );
377 } // namespace detail
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 )
382 return detail::mp_with_index_impl_<N>::template call<0>( i, std::forward<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 )
387 return mp_with_index<std::size_t{N::value}>( i, std::forward<F>(f) );
390 #undef BOOST_MP11_CONSTEXPR14
391 #undef BOOST_MP11_UNREACHABLE
396 #endif // #ifndef BOOST_MP11_DETAIL_MP_WITH_INDEX_HPP_INCLUDED