boostorg / phoenix

Boost.org phoenix module
http://boost.org/libs/phoenix
30 stars 46 forks source link

Actor is taken by reference on assignment/subscript #67

Closed Kojoley closed 6 years ago

Kojoley commented 6 years ago

It looks like I have found the reason why assignment/subscript operators were defined by hand (ref #64) but not with BOOST_PROTO_EXTENDS_SUBSCRIPT/BOOST_PROTO_EXTENDS_ASSIGN.

For unknown reason proto's assignment and subscript operators takes rhs by reference while other operators takes both arguments by value.

Example:

    std::cout << typeid(decltype(boost::phoenix::ref(s) = "asd")).name() << std::endl;
    std::cout << typeid(decltype(boost::phoenix::ref(s) + "asd")).name() << std::endl;
boost::phoenix::actor<
    boost::proto::exprns_::basic_expr<
        boost::proto::tagns_::tag::assign
      , boost::proto::argsns_::list2<
            boost::phoenix::actor<
                boost::proto::exprns_::basic_expr<
                    boost::proto::tagns_::tag::terminal
                  , boost::proto::argsns_::term<
                        boost::reference_wrapper<
                            std::basic_string<
                                char
                              , std::char_traits<char>
                              , std::allocator<char>
                            >
                        >
                    >
                  , 0
                >
            > const & /////////////////////////// HERE
          , boost::phoenix::actor<
                boost::proto::exprns_::basic_expr<
                    boost::proto::tagns_::tag::terminal
                  , boost::proto::argsns_::term<char>
                  , 0
                >
            >
        >
      , 2
    >
>

boost::phoenix::actor<
    boost::proto::exprns_::basic_expr<
        boost::proto::tagns_::tag::plus
      , boost::proto::argsns_::list2<
            boost::phoenix::actor<
                boost::proto::exprns_::basic_expr<
                    boost::proto::tagns_::tag::terminal
                  , boost::proto::argsns_::term<
                        boost::reference_wrapper<
                            std::basic_string<
                                char
                              , std::char_traits<char>
                              , std::allocator<char>
                            >
                        >
                    >
                  , 0
                >
            > /////////////////////////// HERE
          , boost::phoenix::actor<
                boost::proto::exprns_::basic_expr<
                    boost::proto::tagns_::tag::terminal
                  , boost::proto::argsns_::term<char>
                  , 0
                >
            >
        >
      , 2
    >
>
Kojoley commented 6 years ago

I tried to use something like this proto::call<phoenix_generator(proto::call<proto::value(proto::_left)>, proto::_right)> but it did not compile/work. I would be glad for pointing me towards a such working rewrite transformation.

djowel commented 6 years ago

Bam! There you go. I'm sorry my memory of it has slipped me :-/