
Eric Niebler wrote:
I was mistaken about falling foul of RVO. Here is what is happening. You have two domains in play, both with different generators. You compose some expressions in different domains, A and B. Proto decides the resulting expression R should be in domain B. Proto prefers things to be nice and uniform, so before making A a child of R, it puts it also into B's domain by applying B's generator. That causes the extra copy you're seeing. If A and B had had the same generator, no extra invocation of the generator would be performed.
Why does Proto put expression A into B's domain? Good question. It just seemed like the right thing to do when I wrote the code. Right now, that looks like a dubious decision. Lemme think on it for a bit
Don't know if it'll help you but, back in the day where subdomain didn't exist, NT2 used a as(a,b) function to make a comaptible with b. It was like : template<class Y,class C,class X> static inline typename boost::proto::result_of:: make_expr < tags::as_ , containers::domain<typename Y::nt2_category_tag> , containers::expr<X,C> const& >::type const as( containers::expr<X,C> const& xpr, Y const& ) { return boost::proto:: make_expr < tags::as_ , containers::domain<typename Y::nt2_category_tag> > ( boost::cref(xpr) ); } and it worked without any copy as a was stored as a reference in a special node.