Boost logo

Boost :

From: Maurizio Vitale (mav_at_[hidden])
Date: 2007-07-17 13:58:22


Eric Niebler <eric_at_[hidden]> writes:

> Maurizio Vitale wrote:
<snip>
>>
>> My mental model was:
>> - proto::deep_copy traverse the expression top-down replacing references with value.
>
> Actually, bottom-up, but yes references are replaced with values.

It is probably terminology, but the following seems top-down to me: you're asked to deep-copy
an expression and you assemble an expression which has the same shape (tag and argcount) of the
original and as children the result of recursive evaluations of deep-copy on the children.

    #define N BOOST_PP_ITERATION()

            template<typename Expr>
            struct deep_copy_impl<Expr, N>
            {
                typedef expr<typename Expr::proto_tag, BOOST_PP_CAT(args, N)<
                    BOOST_PP_ENUM(N, BOOST_PROTO_DEFINE_DEEP_COPY_TYPE, ~)
> > expr_type;
                typedef typename Expr::proto_domain::template apply<expr_type>::type type;

                template<typename Expr2>
                static type call(Expr2 const &expr)
                {
                    expr_type that = {
                        BOOST_PP_ENUM(N, BOOST_PROTO_DEFINE_DEEP_COPY_FUN, ~)
                    };
                    return Expr::proto_domain::make(that);
                }
            };

>
>> - generators are used to wrap expressions as they are built bottom-up
>
> Generators are used whenever you want to customize the result of proto's
> operator overloads.

Yes, and my reading of the behaviour of the specific generator you wrote is that
everytime you construct an expression you evaluate deep_copy on it.
Modulo the number of evaluations of deep_copy, I still don't see any difference
between using deep_copy on the toplevel expression and using the generator for
building an already deep-copied solution (other than, as you point out later in
one case you have to explicitely call deep_copy while in the other expressions
naturally spring to life without references)

>> So, assuming that the expression is properly wrapped in lambda_expr<> why the result
>> of calling proto::expr on the whole expression would be different from using the generator?
>
> Sorry, I don't understand the question.

I guess my question is what is the difference between:

  struct lambda_domain : domain<generator<lambda_expression> > {};
  auto expr = deep_copy(_1 + 42);

and:

  auto expr_1 = _1 + 42; in the case where the generator you provided is used

Aren't expr and expr_1 exactly the same?

> How this helps is that as phoenix expressions are being built, the
> phoenix generator will ensure that all the nodes are held by-value.
> There will never be a need for the user to deep_copy phoenix expressions
> explicitly -- it's done piecemeal by phoenix. So function<> is passed an
> object that does not need to be deep-copied.

I see this difference now and understand the reasons behind your suggestion.
Thanks for the explanation,

       Maurizio


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk