algo/for_each: Fixed parameter type

to be able to call mutable object
This commit is contained in:
Kohei Takahashi
2018-07-02 22:19:25 +09:00
parent afb8b150a9
commit 0e4c5127f5
6 changed files with 140 additions and 41 deletions

View File

@ -30,7 +30,7 @@ namespace detail
template <typename First, typename Last, typename F> template <typename First, typename Last, typename F>
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
inline void inline void
for_each_linear(First const& first, Last const& last, F const& f, mpl::false_) for_each_linear(First const& first, Last const& last, F& f, mpl::false_)
{ {
f(*first); f(*first);
detail::for_each_linear(fusion::next(first), last, f, detail::for_each_linear(fusion::next(first), last, f,
@ -41,7 +41,7 @@ namespace detail
template <typename Sequence, typename F, typename Tag> template <typename Sequence, typename F, typename Tag>
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
inline void inline void
for_each_dispatch(Sequence& seq, F const& f, Tag) for_each_dispatch(Sequence& seq, F& f, Tag)
{ {
detail::for_each_linear( detail::for_each_linear(
fusion::begin(seq) fusion::begin(seq)
@ -57,7 +57,7 @@ namespace detail
{ {
template<typename I0, typename F> template<typename I0, typename F>
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
static void call(I0 const& i0, F const& f) static void call(I0 const& i0, F& f)
{ {
f(*i0); f(*i0);
typedef typename result_of::next<I0>::type I1; typedef typename result_of::next<I0>::type I1;
@ -78,7 +78,7 @@ namespace detail
{ {
template<typename I0, typename F> template<typename I0, typename F>
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
static void call(I0 const& i0, F const& f) static void call(I0 const& i0, F& f)
{ {
f(*i0); f(*i0);
typedef typename result_of::next<I0>::type I1; typedef typename result_of::next<I0>::type I1;
@ -95,7 +95,7 @@ namespace detail
{ {
template<typename I0, typename F> template<typename I0, typename F>
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
static void call(I0 const& i0, F const& f) static void call(I0 const& i0, F& f)
{ {
f(*i0); f(*i0);
typedef typename result_of::next<I0>::type I1; typedef typename result_of::next<I0>::type I1;
@ -109,7 +109,7 @@ namespace detail
{ {
template<typename I0, typename F> template<typename I0, typename F>
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
static void call(I0 const& i0, F const& f) static void call(I0 const& i0, F& f)
{ {
f(*i0); f(*i0);
} }
@ -128,7 +128,7 @@ namespace detail
template <typename Sequence, typename F> template <typename Sequence, typename F>
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
inline void inline void
for_each_dispatch(Sequence& seq, F const& f, random_access_traversal_tag) for_each_dispatch(Sequence& seq, F& f, random_access_traversal_tag)
{ {
typedef typename result_of::begin<Sequence>::type begin; typedef typename result_of::begin<Sequence>::type begin;
typedef typename result_of::end<Sequence>::type end; typedef typename result_of::end<Sequence>::type end;
@ -138,7 +138,7 @@ namespace detail
template <typename Sequence, typename F> template <typename Sequence, typename F>
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
inline void inline void
for_each(Sequence& seq, F const& f, mpl::false_) // unsegmented implementation for_each(Sequence& seq, F& f, mpl::false_) // unsegmented implementation
{ {
detail::for_each_dispatch(seq, f, typename traits::category_of<Sequence>::type()); detail::for_each_dispatch(seq, f, typename traits::category_of<Sequence>::type());
} }

View File

@ -19,11 +19,11 @@ namespace boost { namespace fusion { namespace detail
struct segmented_for_each_fun struct segmented_for_each_fun
{ {
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
explicit segmented_for_each_fun(Fun const& f) explicit segmented_for_each_fun(Fun& f)
: fun(f) : fun(f)
{} {}
Fun const& fun; Fun& fun;
template <typename Sequence, typename State, typename Context> template <typename Sequence, typename State, typename Context>
struct apply struct apply
@ -43,7 +43,7 @@ namespace boost { namespace fusion { namespace detail
template <typename Sequence, typename F> template <typename Sequence, typename F>
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
inline void inline void
for_each(Sequence& seq, F const& f, mpl::true_) // segmented implementation for_each(Sequence& seq, F& f, mpl::true_) // segmented implementation
{ {
fusion::segmented_fold_until(seq, void_(), segmented_for_each_fun<F>(f)); fusion::segmented_fold_until(seq, void_(), segmented_for_each_fun<F>(f));
} }

View File

@ -1,6 +1,7 @@
/*============================================================================= /*=============================================================================
Copyright (c) 2001-2007 Joel de Guzman Copyright (c) 2001-2007 Joel de Guzman
Copyright (c) 2007 Dan Marsden Copyright (c) 2007 Dan Marsden
Copyright (c) 2018 Kohei Takahashi
Distributed under the Boost Software License, Version 1.0. (See accompanying 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) file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -13,7 +14,7 @@
#include <boost/fusion/algorithm/iteration/detail/segmented_for_each.hpp> #include <boost/fusion/algorithm/iteration/detail/segmented_for_each.hpp>
#include <boost/fusion/support/is_segmented.hpp> #include <boost/fusion/support/is_segmented.hpp>
#include <boost/fusion/support/is_sequence.hpp> #include <boost/fusion/support/is_sequence.hpp>
#include <boost/utility/enable_if.hpp> #include <boost/core/enable_if.hpp>
namespace boost { namespace fusion namespace boost { namespace fusion
{ {
@ -28,24 +29,16 @@ namespace boost { namespace fusion
template <typename Sequence, typename F> template <typename Sequence, typename F>
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
inline typename inline typename enable_if<traits::is_sequence<Sequence> >::type
enable_if< for_each(Sequence& seq, F f)
traits::is_sequence<Sequence>
, void
>::type
for_each(Sequence& seq, F const& f)
{ {
detail::for_each(seq, f, typename traits::is_segmented<Sequence>::type()); detail::for_each(seq, f, typename traits::is_segmented<Sequence>::type());
} }
template <typename Sequence, typename F> template <typename Sequence, typename F>
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
inline typename inline typename enable_if<traits::is_sequence<Sequence> >::type
enable_if< for_each(Sequence const& seq, F f)
traits::is_sequence<Sequence>
, void
>::type
for_each(Sequence const& seq, F const& f)
{ {
detail::for_each(seq, f, typename traits::is_segmented<Sequence>::type()); detail::for_each(seq, f, typename traits::is_segmented<Sequence>::type());
} }

View File

@ -1,5 +1,6 @@
/*============================================================================= /*=============================================================================
Copyright (c) 2011 Eric Niebler Copyright (c) 2011 Eric Niebler
Copyright (c) 2018 Kohei Takahashi
Distributed under the Boost Software License, Version 1.0. (See accompanying 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) file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@ -9,7 +10,7 @@
#include <boost/fusion/support/config.hpp> #include <boost/fusion/support/config.hpp>
#include <boost/fusion/support/is_sequence.hpp> #include <boost/fusion/support/is_sequence.hpp>
#include <boost/utility/enable_if.hpp> #include <boost/core/enable_if.hpp>
namespace boost { namespace fusion namespace boost { namespace fusion
{ {
@ -21,21 +22,13 @@ namespace boost { namespace fusion
template <typename Sequence, typename F> template <typename Sequence, typename F>
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
inline typename inline typename enable_if<traits::is_sequence<Sequence> >::type
enable_if< for_each(Sequence& seq, F f);
traits::is_sequence<Sequence>
, void
>::type
for_each(Sequence& seq, F const& f);
template <typename Sequence, typename F> template <typename Sequence, typename F>
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
inline typename inline typename enable_if<traits::is_sequence<Sequence> >::type
enable_if< for_each(Sequence const& seq, F f);
traits::is_sequence<Sequence>
, void
>::type
for_each(Sequence const& seq, F const& f);
}} }}
#endif #endif

View File

@ -1,13 +1,15 @@
/*============================================================================= /*=============================================================================
Copyright (c) 2001-2011 Joel de Guzman Copyright (c) 2001-2011 Joel de Guzman
Copyright (c) 2018 Kohei Takahashi
Distributed under the Boost Software License, Version 1.0. (See accompanying 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) file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/ ==============================================================================*/
#include <boost/detail/lightweight_test.hpp> #include <boost/core/lightweight_test.hpp>
#include <boost/fusion/container/vector/vector.hpp> #include <boost/fusion/container/vector/vector.hpp>
#include <boost/fusion/adapted/mpl.hpp> #include <boost/fusion/adapted/mpl.hpp>
#include <boost/fusion/sequence/io/out.hpp> #include <boost/fusion/sequence/io/out.hpp>
#include <boost/fusion/sequence/comparison/equal_to.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp> #include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/mpl/vector_c.hpp> #include <boost/mpl/vector_c.hpp>
@ -29,6 +31,15 @@ struct increment
} }
}; };
struct mutable_increment : increment
{
template <typename T>
void operator()(T& v)
{
return increment::operator()(v);
}
};
int int
main() main()
{ {
@ -44,9 +55,20 @@ main()
} }
{ {
char const ruby[] = "Ruby";
typedef vector<int, char, double, char const*> vector_type; typedef vector<int, char, double, char const*> vector_type;
vector_type v(1, 'x', 3.3, "Ruby"); vector_type v(1, 'x', 3.3, ruby);
for_each(v, increment()); for_each(v, increment());
BOOST_TEST_EQ(v, vector_type(2, 'y', 4.3, ruby + 1));
std::cout << v << std::endl;
}
{
char const ruby[] = "Ruby";
typedef vector<int, char, double, char const*> vector_type;
vector_type v(1, 'x', 3.3, ruby);
for_each(v, mutable_increment());
BOOST_TEST_EQ(v, vector_type(2, 'y', 4.3, ruby + 1));
std::cout << v << std::endl; std::cout << v << std::endl;
} }

View File

@ -1,14 +1,17 @@
/*============================================================================= /*=============================================================================
Copyright (c) 2001-2011 Joel de Guzman Copyright (c) 2001-2011 Joel de Guzman
Copyright (c) 2011 Eric Niebler Copyright (c) 2011 Eric Niebler
Copyright (c) 2018 Kohei Takahashi
Distributed under the Boost Software License, Version 1.0. (See accompanying 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) file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/ ==============================================================================*/
#include <boost/detail/lightweight_test.hpp> #include <boost/core/lightweight_test.hpp>
#include <boost/fusion/container/vector/vector.hpp> #include <boost/fusion/container/vector/vector.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/container/generation/make_vector.hpp> #include <boost/fusion/container/generation/make_vector.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/sequence/comparison/equal_to.hpp>
#include <boost/fusion/sequence/io/out.hpp>
#include "../sequence/tree.hpp" #include "../sequence/tree.hpp"
struct print struct print
@ -20,6 +23,31 @@ struct print
} }
}; };
struct increment
{
template <typename T>
void operator()(T& v) const
{
++v;
}
};
struct mutable_increment : increment
{
template <typename T>
void operator()(T& v)
{
return increment::operator()(v);
}
};
template <typename F, typename Tree>
void test(Tree tree, Tree const& expected)
{
boost::fusion::for_each(tree, F());
BOOST_TEST_EQ(tree, expected);
}
int int
main() main()
{ {
@ -42,6 +70,69 @@ main()
) )
, print() , print()
); );
std::cout << std::endl;
}
{
test<increment>(
make_tree(
make_vector(double(0),'B')
, make_tree(
make_vector(1,2,long(3))
, make_tree(make_vector('a','b','c'))
, make_tree(make_vector(short('d'),'e','f'))
)
, make_tree(
make_vector(4,5,6)
, make_tree(make_vector(float(1),'h','i'))
, make_tree(make_vector('j','k','l'))
)
)
, make_tree(
make_vector(double(1),'C')
, make_tree(
make_vector(2,3,long(4))
, make_tree(make_vector('b','c','d'))
, make_tree(make_vector(short('e'),'f','g'))
)
, make_tree(
make_vector(5,6,7)
, make_tree(make_vector(float(2),'i','j'))
, make_tree(make_vector('k','l','m'))
)
)
);
}
{
test<mutable_increment>(
make_tree(
make_vector(double(0),'B')
, make_tree(
make_vector(1,2,long(3))
, make_tree(make_vector('a','b','c'))
, make_tree(make_vector(short('d'),'e','f'))
)
, make_tree(
make_vector(4,5,6)
, make_tree(make_vector(float(1),'h','i'))
, make_tree(make_vector('j','k','l'))
)
)
, make_tree(
make_vector(double(1),'C')
, make_tree(
make_vector(2,3,long(4))
, make_tree(make_vector('b','c','d'))
, make_tree(make_vector(short('e'),'f','g'))
)
, make_tree(
make_vector(5,6,7)
, make_tree(make_vector(float(2),'i','j'))
, make_tree(make_vector('k','l','m'))
)
)
);
} }
return boost::report_errors(); return boost::report_errors();