diff --git a/include/boost/mp11/algorithm.hpp b/include/boost/mp11/algorithm.hpp index ba7eedf..44439dd 100644 --- a/include/boost/mp11/algorithm.hpp +++ b/include/boost/mp11/algorithm.hpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace boost { @@ -823,6 +824,31 @@ template struct mp_replace_at_impl template using mp_replace_at = typename detail::mp_replace_at_impl::type; template using mp_replace_at_c = typename detail::mp_replace_at_impl, W>::type; +namespace detail +{ + +template BOOST_CONSTEXPR F mp_for_each_impl( mp_list, F && f ) +{ + using A = int[sizeof...(T)]; + return (void)A{ ((void)f(mp_identity()), 0)... }, std::forward(f); +} + +#if BOOST_WORKAROUND( BOOST_MSVC, <= 1800 ) + +template BOOST_CONSTEXPR F mp_for_each_impl( mp_list<>, F && f ) +{ + return std::forward(f); +} + +#endif + +} // namespace detail + +template BOOST_CONSTEXPR F mp_for_each( F && f ) +{ + return detail::mp_for_each_impl( mp_rename(), std::forward(f) ); +} + } // namespace mp11 } // namespace boost diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index c627c6b..f7afbe4 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -64,6 +64,7 @@ run mp_any_of.cpp : : : $(REQ) ; run mp_none_of.cpp : : : $(REQ) ; run mp_replace_at.cpp : : : $(REQ) ; run mp_replace_at_c.cpp : : : $(REQ) ; +run mp_for_each.cpp : : : $(REQ) ; # integral run integral.cpp : : : $(REQ) ; diff --git a/test/mp_for_each.cpp b/test/mp_for_each.cpp new file mode 100644 index 0000000..b7d0a21 --- /dev/null +++ b/test/mp_for_each.cpp @@ -0,0 +1,72 @@ + +// 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 +#include + +using boost::mp11::mp_identity; + +#if !defined( BOOST_NO_CXX14_CONSTEXPR ) +# define CONSTEXPR14 constexpr +#else +# define CONSTEXPR14 +#endif + +struct F +{ + int s; + + CONSTEXPR14 void operator()( mp_identity ) { s = s * 10 + 1; } + CONSTEXPR14 void operator()( mp_identity ) { s = s * 10 + 2; } + CONSTEXPR14 void operator()( mp_identity ) { s = s * 10 + 3; } +}; + +using boost::mp11::mp_list; +using boost::mp11::mp_for_each; + +int main() +{ + BOOST_TEST_EQ( (mp_for_each>( 11 )), 11 ); + BOOST_TEST_EQ( (mp_for_each>( F{0} ).s), 1 ); + BOOST_TEST_EQ( (mp_for_each>( F{0} ).s), 12 ); + BOOST_TEST_EQ( (mp_for_each>( F{0} ).s), 123 ); + + BOOST_TEST_EQ( (mp_for_each>( 11 )), 11 ); + BOOST_TEST_EQ( (mp_for_each>( F{0} ).s), 1 ); + BOOST_TEST_EQ( (mp_for_each>( F{0} ).s), 12 ); + BOOST_TEST_EQ( (mp_for_each>( F{0} ).s), 123 ); + + BOOST_TEST_EQ( (mp_for_each>( F{0} ).s), 12 ); + +#if !defined( BOOST_NO_CXX11_CONSTEXPR ) + + static_assert( mp_for_each>( 11 ) == 11, "mp_for_each>( 11 ) == 11" ); + static_assert( mp_for_each>( 12 ) == 12, "mp_for_each>( 12 ) == 12" ); + +#endif + +#if !defined( BOOST_NO_CXX14_CONSTEXPR ) && !BOOST_WORKAROUND( BOOST_MSVC, <= 1910 ) + + constexpr auto r1 = mp_for_each>( F{0} ); + static_assert( r1.s == 123, "r1.s == 123" ); + + constexpr auto r2 = mp_for_each>( F{0} ); + static_assert( r2.s == 123, "r2.s == 123" ); + + constexpr auto r3 = mp_for_each>( F{0} ); + static_assert( r3.s == 12, "r3.s == 12" ); + +#endif + + return boost::report_errors(); +}