diff --git a/doc/html/mp11.html b/doc/html/mp11.html index 2c2c378..90c528f 100644 --- a/doc/html/mp11.html +++ b/doc/html/mp11.html @@ -148,6 +148,8 @@
mp_none_of<L, P>
mp_any_of<L, P>
mp_for_each<L>(f)
+
mp_for_index_c<N>(i, f)
+
mp_for_index<N>(i, f)
Set Operations, <boost/mp11/set.hpp>
@@ -200,7 +202,7 @@
A "for each" algorithm for tuple-like types, <boost/mp11/tuple_for_each.hpp>
-
tuple_for_each
+
tuple_for_each(tp, f)
@@ -2036,6 +2038,29 @@ Returns std::forward<F>(f).

+
+

+mp_for_index_c<N>(i, f) +

+
template<std::size_t N, class F> decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) mp_for_index( std::size_t i, F && f );
+
+

+ mp_for_index_c<N>(i, f) calls f + with mp_size_t<i>() + and returns the result. i + must be less than N. +

+
+
+

+mp_for_index<N>(i, f) +

+
template<class N, class F> decltype(std::declval<F>()(std::declval<mp_size_t<0>>())) mp_for_index( std::size_t i, F && f );
+
+

+ Returns mp_for_index_c<N::value>(i, f). +

+

@@ -2484,7 +2509,7 @@

template<class Tp, class F> constexpr F tuple_for_each(Tp&& tp, F&& f);
 
@@ -2504,7 +2529,7 @@
- +

Last revised: May 28, 2017 at 23:51:44 GMT

Last revised: May 31, 2017 at 16:52:56 GMT


diff --git a/doc/mp11/algorithm.qbk b/doc/mp11/algorithm.qbk index 08f7a53..8fa6d63 100644 --- a/doc/mp11/algorithm.qbk +++ b/doc/mp11/algorithm.qbk @@ -289,4 +289,16 @@ is `mp_size`. Returns `std::forward(f)`. [endsect] +[section `mp_for_index_c(i, f)`] + template decltype(std::declval()(std::declval>())) mp_for_index( std::size_t i, F && f ); + +`mp_for_index_c(i, f)` calls `f` with `mp_size_t()` and returns the result. `i` must be less than `N`. +[endsect] + +[section `mp_for_index(i, f)`] + template decltype(std::declval()(std::declval>())) mp_for_index( std::size_t i, F && f ); + +Returns `mp_for_index_c(i, f)`. +[endsect] + [endsect:algorithm] diff --git a/doc/mp11/tuple_for_each.qbk b/doc/mp11/tuple_for_each.qbk index 7b1f53e..9ba4c5b 100644 --- a/doc/mp11/tuple_for_each.qbk +++ b/doc/mp11/tuple_for_each.qbk @@ -8,7 +8,7 @@ [section:tuple_for_each A "for each" algorithm for tuple-like types, ``] -[section `tuple_for_each`] +[section `tuple_for_each(tp, f)`] template constexpr F tuple_for_each(Tp&& tp, F&& f); `tuple_for_each(tp, f)` applies the function object `f` to each element of `tp` by evaluating the diff --git a/include/boost/mp11/algorithm.hpp b/include/boost/mp11/algorithm.hpp index 5d27cba..f9e409f 100644 --- a/include/boost/mp11/algorithm.hpp +++ b/include/boost/mp11/algorithm.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/include/boost/mp11/detail/mp_for_index.hpp b/include/boost/mp11/detail/mp_for_index.hpp new file mode 100644 index 0000000..ca7eb83 --- /dev/null +++ b/include/boost/mp11/detail/mp_for_index.hpp @@ -0,0 +1,365 @@ +#ifndef BOOST_MP11_DETAIL_MP_FOR_INDEX_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_FOR_INDEX_HPP_INCLUDED + +// Copyright 2017 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 +#include +#include +#include + +namespace boost +{ +namespace mp11 +{ + +namespace detail +{ + +template struct mp_for_index_impl_ +{ + template static decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + case 8: return std::forward(f)( mp_size_t() ); + case 9: return std::forward(f)( mp_size_t() ); + case 10: return std::forward(f)( mp_size_t() ); + case 11: return std::forward(f)( mp_size_t() ); + case 12: return std::forward(f)( mp_size_t() ); + case 13: return std::forward(f)( mp_size_t() ); + case 14: return std::forward(f)( mp_size_t() ); + case 15: return std::forward(f)( mp_size_t() ); + } + + return mp_for_index_impl_::template call( i-16, std::forward(f) ); + } +}; + +template<> struct mp_for_index_impl_<0> +{ +}; + +template<> struct mp_for_index_impl_<1> +{ + template static decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + return std::forward(f)( mp_size_t() ); + } +}; + +template<> struct mp_for_index_impl_<2> +{ + template static decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_for_index_impl_<3> +{ + template static decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_for_index_impl_<4> +{ + template static decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_for_index_impl_<5> +{ + template static decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_for_index_impl_<6> +{ + template static decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_for_index_impl_<7> +{ + template static decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_for_index_impl_<8> +{ + template static decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_for_index_impl_<9> +{ + template static decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + case 8: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_for_index_impl_<10> +{ + template static decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + case 8: return std::forward(f)( mp_size_t() ); + case 9: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_for_index_impl_<11> +{ + template static decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + case 8: return std::forward(f)( mp_size_t() ); + case 9: return std::forward(f)( mp_size_t() ); + case 10: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_for_index_impl_<12> +{ + template static decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + case 8: return std::forward(f)( mp_size_t() ); + case 9: return std::forward(f)( mp_size_t() ); + case 10: return std::forward(f)( mp_size_t() ); + case 11: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_for_index_impl_<13> +{ + template static decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + case 8: return std::forward(f)( mp_size_t() ); + case 9: return std::forward(f)( mp_size_t() ); + case 10: return std::forward(f)( mp_size_t() ); + case 11: return std::forward(f)( mp_size_t() ); + case 12: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_for_index_impl_<14> +{ + template static decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + case 8: return std::forward(f)( mp_size_t() ); + case 9: return std::forward(f)( mp_size_t() ); + case 10: return std::forward(f)( mp_size_t() ); + case 11: return std::forward(f)( mp_size_t() ); + case 12: return std::forward(f)( mp_size_t() ); + case 13: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_for_index_impl_<15> +{ + template static decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + case 8: return std::forward(f)( mp_size_t() ); + case 9: return std::forward(f)( mp_size_t() ); + case 10: return std::forward(f)( mp_size_t() ); + case 11: return std::forward(f)( mp_size_t() ); + case 12: return std::forward(f)( mp_size_t() ); + case 13: return std::forward(f)( mp_size_t() ); + case 14: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_for_index_impl_<16> +{ + template static decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + case 8: return std::forward(f)( mp_size_t() ); + case 9: return std::forward(f)( mp_size_t() ); + case 10: return std::forward(f)( mp_size_t() ); + case 11: return std::forward(f)( mp_size_t() ); + case 12: return std::forward(f)( mp_size_t() ); + case 13: return std::forward(f)( mp_size_t() ); + case 14: return std::forward(f)( mp_size_t() ); + case 15: return std::forward(f)( mp_size_t() ); + } + } +}; + +} // namespace detail + +template inline decltype(std::declval()(std::declval>())) mp_for_index_c( std::size_t i, F && f ) +{ + assert( i < N ); + return detail::mp_for_index_impl_::template call<0>( i, std::forward(f) ); +} + +template inline decltype(std::declval()(std::declval>())) mp_for_index( std::size_t i, F && f ) +{ + return mp_for_index_c( i, std::forward(f) ); +} + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_FIND_INDEX_HPP_INCLUDED diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index b086740..c9b8fc8 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -71,6 +71,7 @@ run mp_replace_at_c.cpp : : : $(REQ) ; run mp_for_each.cpp : : : $(REQ) ; run mp_insert.cpp : : : $(REQ) ; run mp_erase.cpp : : : $(REQ) ; +run mp_for_index.cpp : : : $(REQ) ; # integral run integral.cpp : : : $(REQ) ; diff --git a/test/mp_for_index.cpp b/test/mp_for_index.cpp new file mode 100644 index 0000000..d700cad --- /dev/null +++ b/test/mp_for_index.cpp @@ -0,0 +1,90 @@ + +// Copyright 2017 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 +#include +#include +#include +#include + +using boost::mp11::mp_size_t; +using boost::mp11::mp_for_each; +using boost::mp11::mp_for_index; +using boost::mp11::mp_for_index_c; +using boost::mp11::mp_iota_c; + +struct F +{ + int i_; + + explicit F( int i ): i_( i ) {} + + template void operator()( mp_size_t ) const + { + BOOST_TEST_EQ( I, i_ ); + } +}; + +struct G +{ + void operator()( mp_size_t<0> ) const + { + } + + template void operator()( mp_size_t ) const + { + for( std::size_t i = 0; i < N; ++i ) + { + mp_for_index_c( i, F(i) ); + mp_for_index>( i, F(i) ); + } + } +}; + +int main() +{ +#if BOOST_WORKAROUND( BOOST_MSVC, < 1900 ) + + G()( mp_size_t<1>{} ); + G()( mp_size_t<2>{} ); + G()( mp_size_t<3>{} ); + G()( mp_size_t<4>{} ); + G()( mp_size_t<5>{} ); + G()( mp_size_t<6>{} ); + G()( mp_size_t<7>{} ); + G()( mp_size_t<8>{} ); + G()( mp_size_t<9>{} ); + G()( mp_size_t<10>{} ); + G()( mp_size_t<11>{} ); + G()( mp_size_t<12>{} ); + G()( mp_size_t<13>{} ); + G()( mp_size_t<14>{} ); + G()( mp_size_t<15>{} ); + G()( mp_size_t<16>{} ); + + G()( mp_size_t<32+1>{} ); + + G()( mp_size_t<48+2>{} ); + + G()( mp_size_t<64+3>{} ); + + G()( mp_size_t<96+4>{} ); + + G()( mp_size_t<112+5>{} ); + + G()( mp_size_t<128+6>{} ); + +#else + + mp_for_each>( G() ); + +#endif + + return boost::report_errors(); +}