File indexing completed on 2025-01-30 09:46:51
0001 #ifndef BOOST_MP11_DETAIL_MP_WITH_INDEX_HPP_INCLUDED
0002 #define BOOST_MP11_DETAIL_MP_WITH_INDEX_HPP_INCLUDED
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <boost/mp11/integral.hpp>
0012 #include <boost/mp11/detail/config.hpp>
0013 #include <type_traits>
0014 #include <utility>
0015 #include <cassert>
0016
0017 #if defined( BOOST_MP11_HAS_CXX14_CONSTEXPR )
0018 # define BOOST_MP11_CONSTEXPR14 constexpr
0019 #else
0020 # define BOOST_MP11_CONSTEXPR14
0021 #endif
0022
0023 #if defined( __GNUC__ ) || defined( __clang__ )
0024 # define BOOST_MP11_UNREACHABLE_DEFAULT default: __builtin_unreachable();
0025 #elif defined( _MSC_VER )
0026 # define BOOST_MP11_UNREACHABLE_DEFAULT default: __assume(false);
0027 #else
0028 # define BOOST_MP11_UNREACHABLE_DEFAULT
0029 #endif
0030
0031 namespace boost
0032 {
0033 namespace mp11
0034 {
0035
0036 namespace detail
0037 {
0038
0039 template<std::size_t N> struct mp_with_index_impl_
0040 {
0041 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 )
0042 {
0043 if( i < N / 2 )
0044 {
0045 return mp_with_index_impl_<N/2>::template call<K>( i, std::forward<F>(f) );
0046 }
0047 else
0048 {
0049 return mp_with_index_impl_<N-N/2>::template call<K+N/2>( i - N/2, std::forward<F>(f) );
0050 }
0051 }
0052 };
0053
0054 template<> struct mp_with_index_impl_<0>
0055 {
0056 };
0057
0058 template<> struct mp_with_index_impl_<1>
0059 {
0060 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 , F && f )
0061 {
0062 return std::forward<F>(f)( mp_size_t<K+0>() );
0063 }
0064 };
0065
0066 template<> struct mp_with_index_impl_<2>
0067 {
0068 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 )
0069 {
0070 switch( i )
0071 {
0072 BOOST_MP11_UNREACHABLE_DEFAULT
0073 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
0074 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
0075 }
0076 }
0077 };
0078
0079 template<> struct mp_with_index_impl_<3>
0080 {
0081 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 )
0082 {
0083 switch( i )
0084 {
0085 BOOST_MP11_UNREACHABLE_DEFAULT
0086 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
0087 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
0088 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
0089 }
0090 }
0091 };
0092
0093 template<> struct mp_with_index_impl_<4>
0094 {
0095 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 )
0096 {
0097 switch( i )
0098 {
0099 BOOST_MP11_UNREACHABLE_DEFAULT
0100 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
0101 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
0102 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
0103 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
0104 }
0105 }
0106 };
0107
0108 template<> struct mp_with_index_impl_<5>
0109 {
0110 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 )
0111 {
0112 switch( i )
0113 {
0114 BOOST_MP11_UNREACHABLE_DEFAULT
0115 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
0116 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
0117 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
0118 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
0119 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
0120 }
0121 }
0122 };
0123
0124 template<> struct mp_with_index_impl_<6>
0125 {
0126 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 )
0127 {
0128 switch( i )
0129 {
0130 BOOST_MP11_UNREACHABLE_DEFAULT
0131 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
0132 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
0133 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
0134 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
0135 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
0136 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
0137 }
0138 }
0139 };
0140
0141 template<> struct mp_with_index_impl_<7>
0142 {
0143 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 )
0144 {
0145 switch( i )
0146 {
0147 BOOST_MP11_UNREACHABLE_DEFAULT
0148 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
0149 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
0150 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
0151 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
0152 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
0153 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
0154 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
0155 }
0156 }
0157 };
0158
0159 template<> struct mp_with_index_impl_<8>
0160 {
0161 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 )
0162 {
0163 switch( i )
0164 {
0165 BOOST_MP11_UNREACHABLE_DEFAULT
0166 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
0167 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
0168 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
0169 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
0170 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
0171 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
0172 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
0173 case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
0174 }
0175 }
0176 };
0177
0178 template<> struct mp_with_index_impl_<9>
0179 {
0180 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 )
0181 {
0182 switch( i )
0183 {
0184 BOOST_MP11_UNREACHABLE_DEFAULT
0185 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
0186 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
0187 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
0188 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
0189 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
0190 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
0191 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
0192 case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
0193 case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
0194 }
0195 }
0196 };
0197
0198 template<> struct mp_with_index_impl_<10>
0199 {
0200 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 )
0201 {
0202 switch( i )
0203 {
0204 BOOST_MP11_UNREACHABLE_DEFAULT
0205 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
0206 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
0207 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
0208 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
0209 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
0210 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
0211 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
0212 case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
0213 case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
0214 case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
0215 }
0216 }
0217 };
0218
0219 template<> struct mp_with_index_impl_<11>
0220 {
0221 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 )
0222 {
0223 switch( i )
0224 {
0225 BOOST_MP11_UNREACHABLE_DEFAULT
0226 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
0227 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
0228 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
0229 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
0230 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
0231 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
0232 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
0233 case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
0234 case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
0235 case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
0236 case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
0237 }
0238 }
0239 };
0240
0241 template<> struct mp_with_index_impl_<12>
0242 {
0243 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 )
0244 {
0245 switch( i )
0246 {
0247 BOOST_MP11_UNREACHABLE_DEFAULT
0248 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
0249 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
0250 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
0251 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
0252 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
0253 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
0254 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
0255 case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
0256 case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
0257 case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
0258 case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
0259 case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
0260 }
0261 }
0262 };
0263
0264 template<> struct mp_with_index_impl_<13>
0265 {
0266 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 )
0267 {
0268 switch( i )
0269 {
0270 BOOST_MP11_UNREACHABLE_DEFAULT
0271 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
0272 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
0273 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
0274 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
0275 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
0276 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
0277 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
0278 case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
0279 case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
0280 case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
0281 case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
0282 case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
0283 case 12: return std::forward<F>(f)( mp_size_t<K+12>() );
0284 }
0285 }
0286 };
0287
0288 template<> struct mp_with_index_impl_<14>
0289 {
0290 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 )
0291 {
0292 switch( i )
0293 {
0294 BOOST_MP11_UNREACHABLE_DEFAULT
0295 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
0296 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
0297 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
0298 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
0299 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
0300 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
0301 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
0302 case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
0303 case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
0304 case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
0305 case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
0306 case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
0307 case 12: return std::forward<F>(f)( mp_size_t<K+12>() );
0308 case 13: return std::forward<F>(f)( mp_size_t<K+13>() );
0309 }
0310 }
0311 };
0312
0313 template<> struct mp_with_index_impl_<15>
0314 {
0315 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 )
0316 {
0317 switch( i )
0318 {
0319 BOOST_MP11_UNREACHABLE_DEFAULT
0320 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
0321 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
0322 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
0323 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
0324 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
0325 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
0326 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
0327 case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
0328 case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
0329 case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
0330 case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
0331 case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
0332 case 12: return std::forward<F>(f)( mp_size_t<K+12>() );
0333 case 13: return std::forward<F>(f)( mp_size_t<K+13>() );
0334 case 14: return std::forward<F>(f)( mp_size_t<K+14>() );
0335 }
0336 }
0337 };
0338
0339 template<> struct mp_with_index_impl_<16>
0340 {
0341 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 )
0342 {
0343 switch( i )
0344 {
0345 BOOST_MP11_UNREACHABLE_DEFAULT
0346 case 0: return std::forward<F>(f)( mp_size_t<K+0>() );
0347 case 1: return std::forward<F>(f)( mp_size_t<K+1>() );
0348 case 2: return std::forward<F>(f)( mp_size_t<K+2>() );
0349 case 3: return std::forward<F>(f)( mp_size_t<K+3>() );
0350 case 4: return std::forward<F>(f)( mp_size_t<K+4>() );
0351 case 5: return std::forward<F>(f)( mp_size_t<K+5>() );
0352 case 6: return std::forward<F>(f)( mp_size_t<K+6>() );
0353 case 7: return std::forward<F>(f)( mp_size_t<K+7>() );
0354 case 8: return std::forward<F>(f)( mp_size_t<K+8>() );
0355 case 9: return std::forward<F>(f)( mp_size_t<K+9>() );
0356 case 10: return std::forward<F>(f)( mp_size_t<K+10>() );
0357 case 11: return std::forward<F>(f)( mp_size_t<K+11>() );
0358 case 12: return std::forward<F>(f)( mp_size_t<K+12>() );
0359 case 13: return std::forward<F>(f)( mp_size_t<K+13>() );
0360 case 14: return std::forward<F>(f)( mp_size_t<K+14>() );
0361 case 15: return std::forward<F>(f)( mp_size_t<K+15>() );
0362 }
0363 }
0364 };
0365
0366 }
0367
0368 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 )
0369 {
0370 assert( i < N );
0371 return detail::mp_with_index_impl_<N>::template call<0>( i, std::forward<F>(f) );
0372 }
0373
0374 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 )
0375 {
0376 return mp_with_index<std::size_t{N::value}>( i, std::forward<F>(f) );
0377 }
0378
0379 #undef BOOST_MP11_CONSTEXPR14
0380 #undef BOOST_MP11_UNREACHABLE_DEFAULT
0381
0382 }
0383 }
0384
0385 #endif