diff --git a/include/boost/tuple_for_each.hpp b/include/boost/tuple_for_each.hpp new file mode 100644 index 0000000..35d2b7a --- /dev/null +++ b/include/boost/tuple_for_each.hpp @@ -0,0 +1,33 @@ +#ifndef BOOST_TUPLE_FOR_EACH_HPP_INCLUDED +#define BOOST_TUPLE_FOR_EACH_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + +namespace detail +{ + +template BOOST_CONSTEXPR F tuple_for_each_impl( Tp && tp, boost::integer_sequence, F && f ) +{ + using A = int[sizeof...(J)]; + return (void)A{ (f(std::get(std::forward(tp))), 0)... }, std::forward(f); +} + +} // namespace detail + +template BOOST_CONSTEXPR F tuple_for_each( Tp && tp, F && f ) +{ + using seq = boost::make_index_sequence::type>::value>; + return detail::tuple_for_each_impl( std::forward(tp), seq(), std::forward(f) ); +} + +} // namespace boost + +#endif // #ifndef BOOST_TUPLE_FOR_EACH_HPP_INCLUDED diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 1feb47e..9118ff4 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -52,3 +52,7 @@ run mp_eval_if.cpp : : : $(REQ) ; # integer_sequence run integer_sequence.cpp : : : $(REQ) ; + +# tuple_for_each +run tuple_for_each.cpp : : : $(REQ) ; +run tuple_for_each_cx.cpp : : : $(REQ) ; diff --git a/test/tuple_for_each.cpp b/test/tuple_for_each.cpp new file mode 100644 index 0000000..325a51e --- /dev/null +++ b/test/tuple_for_each.cpp @@ -0,0 +1,90 @@ + +// Copyright 2015 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 + +int main() +{ + { + std::tuple tp{ 1, 2, 3 }; + + { + int s = 0; + + boost::tuple_for_each( tp, [&]( int x ){ s = s * 10 + x; } ); + + BOOST_TEST_EQ( s, 123 ); + } + + { + int s = 0; + + boost::tuple_for_each( std::move(tp), [&]( int x ){ s = s * 10 + x; } ); + + BOOST_TEST_EQ( s, 123 ); + } + } + + { + std::tuple, std::unique_ptr, std::unique_ptr> tp{ std::unique_ptr(new int(1)), std::unique_ptr(new int(2)), std::unique_ptr(new int(3)) }; + + int s = 0; + + boost::tuple_for_each( std::move(tp), [&]( std::unique_ptr p ){ s = s * 10 + *p; } ); + + BOOST_TEST_EQ( s, 123 ); + } + + { + std::pair tp{ 1, 2 }; + + { + int s = 0; + + boost::tuple_for_each( tp, [&]( int x ){ s = s * 10 + x; } ); + + BOOST_TEST_EQ( s, 12 ); + } + + { + int s = 0; + + boost::tuple_for_each( std::move(tp), [&]( int x ){ s = s * 10 + x; } ); + + BOOST_TEST_EQ( s, 12 ); + } + } + + { + std::array tp{{ 1, 2, 3 }}; + + { + int s = 0; + + boost::tuple_for_each( tp, [&]( int x ){ s = s * 10 + x; } ); + + BOOST_TEST_EQ( s, 123 ); + } + + { + int s = 0; + + boost::tuple_for_each( std::move(tp), [&]( int x ){ s = s * 10 + x; } ); + + BOOST_TEST_EQ( s, 123 ); + } + } + + return boost::report_errors(); +} diff --git a/test/tuple_for_each_cx.cpp b/test/tuple_for_each_cx.cpp new file mode 100644 index 0000000..220253c --- /dev/null +++ b/test/tuple_for_each_cx.cpp @@ -0,0 +1,37 @@ + +// Copyright 2015 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 + +#if defined( BOOST_NO_CXX11_CONSTEXPR ) + +int main() {} + +#else + +#include +#include + +struct assert_is_integral +{ + template constexpr bool operator()( T ) const + { + static_assert( std::is_integral::value, "T must be an integral type" ); + return true; + } +}; + +int main() +{ + constexpr std::tuple tp{ 1, 2, 3 }; + constexpr auto r = boost::tuple_for_each( tp, assert_is_integral() ); + (void)r; +} + +#endif