From 8fe8312b7e77932f7e145eef9dcc91d80b46f724 Mon Sep 17 00:00:00 2001 From: Thomas Heller Date: Sat, 22 Jan 2011 18:23:32 +0000 Subject: [PATCH] made phoenix actor Assignable [SVN r68369] --- include/boost/phoenix/core/actor.hpp | 63 ++++++++++++++++- .../bind_and_or_test.cpp | 26 +++---- .../bind_const_test.cpp | 44 ++++++------ .../bind_not_test.cpp | 10 +-- test/bug4853.cpp | 70 +++++++++++++++++++ 5 files changed, 172 insertions(+), 41 deletions(-) create mode 100644 test/bug4853.cpp diff --git a/include/boost/phoenix/core/actor.hpp b/include/boost/phoenix/core/actor.hpp index b1cfc67..9b1d499 100644 --- a/include/boost/phoenix/core/actor.hpp +++ b/include/boost/phoenix/core/actor.hpp @@ -21,6 +21,7 @@ #include #include #include +#include namespace boost { namespace phoenix { @@ -40,6 +41,54 @@ namespace boost { namespace phoenix template error_invalid_lambda_expr(T const&) {} }; + + struct do_assign + { + BOOST_PROTO_CALLABLE() + + typedef void result_type; + + template + void operator()(T1 & t1, T2 const & t2) const + { + proto::value(t1) = proto::value(t2); + } + }; + + + #define PHOENIX_ACTOR_ASSIGN_CHILD(Z, N, D) \ + assign(proto::_child_c, proto::_child_c(proto::_state)) \ + /**/ + #define PHOENIX_ACTOR_ASSIGN_CALL(Z, N, D) \ + proto::when< \ + proto::nary_expr \ + , proto::and_< \ + BOOST_PP_ENUM( \ + N \ + , PHOENIX_ACTOR_ASSIGN_CHILD \ + , _ \ + ) \ + > \ + > \ + /**/ + + struct assign + : proto::or_< + BOOST_PP_ENUM_SHIFTED( + PHOENIX_LIMIT + , PHOENIX_ACTOR_ASSIGN_CALL + , _ + ) + , proto::when< + proto::terminal + , do_assign(proto::_, proto::_state) + > + > + {}; + #undef PHOENIX_ACTOR_ASSIGN_CALL + #undef PHOENIX_ACTOR_ASSIGN_CHILD } // Bring in the result_of::actor<> @@ -58,7 +107,19 @@ namespace boost { namespace phoenix struct actor { BOOST_PROTO_BASIC_EXTENDS(Expr, actor, phoenix_domain) - BOOST_PROTO_EXTENDS_ASSIGN() + + // providing operator= to be assignable + actor& operator=(actor const& other) + { + detail::assign()(*this, other); + return *this; + } + actor& operator=(actor & other) + { + detail::assign()(*this, other); + return *this; + } + BOOST_PROTO_EXTENDS_ASSIGN_() BOOST_PROTO_EXTENDS_SUBSCRIPT() template diff --git a/test/boost_bind_compatibility/bind_and_or_test.cpp b/test/boost_bind_compatibility/bind_and_or_test.cpp index c1603e0..b88c2b5 100644 --- a/test/boost_bind_compatibility/bind_and_or_test.cpp +++ b/test/boost_bind_compatibility/bind_and_or_test.cpp @@ -35,7 +35,7 @@ h() template void -test(F f, A1 a1, A2 a2, R r) +tester(F f, A1 a1, A2 a2, R r) { BOOST_TEST(f(a1, a2) == r); } @@ -48,27 +48,27 @@ int main() // && - test(bind(f, true) && bind(g, true), false, false, f(true) && g(true)); - test(bind(f, true) && bind(g, false), false, false, f(true) && g(false)); + tester(bind(f, true) && bind(g, true), false, false, f(true) && g(true)); + tester(bind(f, true) && bind(g, false), false, false, f(true) && g(false)); - test(bind(f, false) && bind(h), false, false, f(false) && h()); + tester(bind(f, false) && bind(h), false, false, f(false) && h()); - test(bind(f, _1) && bind(g, _2), true, true, f(true) && g(true)); - test(bind(f, _1) && bind(g, _2), true, false, f(true) && g(false)); + tester(bind(f, _1) && bind(g, _2), true, true, f(true) && g(true)); + tester(bind(f, _1) && bind(g, _2), true, false, f(true) && g(false)); - test(bind(f, _1) && bind(h), false, false, f(false) && h()); + tester(bind(f, _1) && bind(h), false, false, f(false) && h()); // || - test(bind(f, false) || bind(g, true), false, false, f(false) || g(true)); - test(bind(f, false) || bind(g, false), false, false, f(false) || g(false)); + tester(bind(f, false) || bind(g, true), false, false, f(false) || g(true)); + tester(bind(f, false) || bind(g, false), false, false, f(false) || g(false)); - test(bind(f, true) || bind(h), false, false, f(true) || h()); + tester(bind(f, true) || bind(h), false, false, f(true) || h()); - test(bind(f, _1) || bind(g, _2), false, true, f(false) || g(true)); - test(bind(f, _1) || bind(g, _2), false, false, f(false) || g(false)); + tester(bind(f, _1) || bind(g, _2), false, true, f(false) || g(true)); + tester(bind(f, _1) || bind(g, _2), false, false, f(false) || g(false)); - test(bind(f, _1) || (h), true, false, f(true) || h()); + tester(bind(f, _1) || (h), true, false, f(true) || h()); // diff --git a/test/boost_bind_compatibility/bind_const_test.cpp b/test/boost_bind_compatibility/bind_const_test.cpp index ed7c9e3..7c1daab 100644 --- a/test/boost_bind_compatibility/bind_const_test.cpp +++ b/test/boost_bind_compatibility/bind_const_test.cpp @@ -136,12 +136,12 @@ void fv_9(long a, long b, long c, long d, long e, long f, long g, long h, long i global_result = a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g + 10000000 * h + 100000000 * i; } -template long test(F const & f, A const & a) +template long tester(F const & f, A const & a) { return f(a); } -template long testv(F const & f, A const & a) +template long testerv(F const & f, A const & a) { f(a); return global_result; @@ -154,27 +154,27 @@ void function_test() int const i = 1; - BOOST_TEST( test( bind(f_0), i ) == 17041L ); - BOOST_TEST( test( bind(f_1, _1), i ) == 1L ); - BOOST_TEST( test( bind(f_2, _1, 2), i ) == 21L ); - BOOST_TEST( test( bind(f_3, _1, 2, 3), i ) == 321L ); - BOOST_TEST( test( bind(f_4, _1, 2, 3, 4), i ) == 4321L ); - BOOST_TEST( test( bind(f_5, _1, 2, 3, 4, 5), i ) == 54321L ); - BOOST_TEST( test( bind(f_6, _1, 2, 3, 4, 5, 6), i ) == 654321L ); - BOOST_TEST( test( bind(f_7, _1, 2, 3, 4, 5, 6, 7), i ) == 7654321L ); - BOOST_TEST( test( bind(f_8, _1, 2, 3, 4, 5, 6, 7, 8), i ) == 87654321L ); - BOOST_TEST( test( bind(f_9, _1, 2, 3, 4, 5, 6, 7, 8, 9), i ) == 987654321L ); + BOOST_TEST( tester( bind(f_0), i ) == 17041L ); + BOOST_TEST( tester( bind(f_1, _1), i ) == 1L ); + BOOST_TEST( tester( bind(f_2, _1, 2), i ) == 21L ); + BOOST_TEST( tester( bind(f_3, _1, 2, 3), i ) == 321L ); + BOOST_TEST( tester( bind(f_4, _1, 2, 3, 4), i ) == 4321L ); + BOOST_TEST( tester( bind(f_5, _1, 2, 3, 4, 5), i ) == 54321L ); + BOOST_TEST( tester( bind(f_6, _1, 2, 3, 4, 5, 6), i ) == 654321L ); + BOOST_TEST( tester( bind(f_7, _1, 2, 3, 4, 5, 6, 7), i ) == 7654321L ); + BOOST_TEST( tester( bind(f_8, _1, 2, 3, 4, 5, 6, 7, 8), i ) == 87654321L ); + BOOST_TEST( tester( bind(f_9, _1, 2, 3, 4, 5, 6, 7, 8, 9), i ) == 987654321L ); - BOOST_TEST( testv( bind(fv_0), i ) == 17041L ); - BOOST_TEST( testv( bind(fv_1, _1), i ) == 1L ); - BOOST_TEST( testv( bind(fv_2, _1, 2), i ) == 21L ); - BOOST_TEST( testv( bind(fv_3, _1, 2, 3), i ) == 321L ); - BOOST_TEST( testv( bind(fv_4, _1, 2, 3, 4), i ) == 4321L ); - BOOST_TEST( testv( bind(fv_5, _1, 2, 3, 4, 5), i ) == 54321L ); - BOOST_TEST( testv( bind(fv_6, _1, 2, 3, 4, 5, 6), i ) == 654321L ); - BOOST_TEST( testv( bind(fv_7, _1, 2, 3, 4, 5, 6, 7), i ) == 7654321L ); - BOOST_TEST( testv( bind(fv_8, _1, 2, 3, 4, 5, 6, 7, 8), i ) == 87654321L ); - BOOST_TEST( testv( bind(fv_9, _1, 2, 3, 4, 5, 6, 7, 8, 9), i ) == 987654321L ); + BOOST_TEST( testerv( bind(fv_0), i ) == 17041L ); + BOOST_TEST( testerv( bind(fv_1, _1), i ) == 1L ); + BOOST_TEST( testerv( bind(fv_2, _1, 2), i ) == 21L ); + BOOST_TEST( testerv( bind(fv_3, _1, 2, 3), i ) == 321L ); + BOOST_TEST( testerv( bind(fv_4, _1, 2, 3, 4), i ) == 4321L ); + BOOST_TEST( testerv( bind(fv_5, _1, 2, 3, 4, 5), i ) == 54321L ); + BOOST_TEST( testerv( bind(fv_6, _1, 2, 3, 4, 5, 6), i ) == 654321L ); + BOOST_TEST( testerv( bind(fv_7, _1, 2, 3, 4, 5, 6, 7), i ) == 7654321L ); + BOOST_TEST( testerv( bind(fv_8, _1, 2, 3, 4, 5, 6, 7, 8), i ) == 87654321L ); + BOOST_TEST( testerv( bind(fv_9, _1, 2, 3, 4, 5, 6, 7, 8, 9), i ) == 987654321L ); } int main() diff --git a/test/boost_bind_compatibility/bind_not_test.cpp b/test/boost_bind_compatibility/bind_not_test.cpp index b9960f6..e499806 100644 --- a/test/boost_bind_compatibility/bind_not_test.cpp +++ b/test/boost_bind_compatibility/bind_not_test.cpp @@ -32,7 +32,7 @@ #include -template void test( F f, A1 a1, R r ) +template void tester( F f, A1 a1, R r ) { BOOST_TEST( f(a1) == r ); } @@ -52,10 +52,10 @@ int main() using boost::phoenix::bind; using boost::phoenix::placeholders::_1; - test( !bind( f, true ), 0, !f( true ) ); - test( !bind( g, _1 ), 5, !g( 5 ) ); - test( bind( f, !bind( f, true ) ), 0, f( !f( true ) ) ); - test( bind( f, !bind( f, _1 ) ), true, f( !f( true ) ) ); + tester( !bind( f, true ), 0, !f( true ) ); + tester( !bind( g, _1 ), 5, !g( 5 ) ); + tester( bind( f, !bind( f, true ) ), 0, f( !f( true ) ) ); + tester( bind( f, !bind( f, _1 ) ), true, f( !f( true ) ) ); return boost::report_errors(); } diff --git a/test/bug4853.cpp b/test/bug4853.cpp new file mode 100644 index 0000000..f63fb9d --- /dev/null +++ b/test/bug4853.cpp @@ -0,0 +1,70 @@ +/*============================================================================== + Copyright (c) 2005-2010 Joel de Guzman + Copyright (c) 2010 Thomas Heller + + 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 +#include +#include +#include + +#include +#include + + +namespace phoenix = boost::phoenix; + +struct Foo { + Foo(const std::string& name, int value) + : name_(name) + , value_(value) + { } + + std::string name_; int value_; +}; + +typedef boost::shared_ptr FooPtr; + +int range_test_complex() { + typedef std::vector V; + + V source; + + source.push_back(boost::make_shared("Foo", 10)); + source.push_back(boost::make_shared("Bar", 20)); + source.push_back(boost::make_shared("Baz", 30)); + source.push_back(boost::make_shared("Baz", 30)); //duplicate is here + + std::vector result1; + std::vector result2; + + using namespace boost::adaptors; + using phoenix::arg_names::arg1; + + boost::push_back(result1, source | transformed(phoenix::bind(&Foo::name_, *arg1)) | uniqued); + + for(unsigned i = 0; i < result1.size(); ++i) + std::cout << result1[i] << "\n"; + + boost::push_back(result2, source | transformed(phoenix::bind(&Foo::value_, *arg1)) | uniqued); + + for(unsigned i = 0; i < result2.size(); ++i) + std::cout << result2[i] << "\n"; + + return 0; + +} + +int main() +{ + return range_test_complex(); +} +