
Eric, I'm trying to following your suggestion of putting data inside what used to be a simple tag and then extend it. This is a simplified version of what I need, without non-default contexts and domains. The problem I'm seeng seems to have to do with display_expr (e.g. the naked expressions alone seems to compile, although I'm not sure how smart the compiler is allowed to do when values are unused and everything is visible within the same file). display_expr is very nice to have, and I think will be even more useful when I'll start with transformations. There're other behaviours of it that looks strange to me, I'll try to reduce them to small examples asap. I see that in debug.hpp you handle the case of 1 and 2 arguments explicitely and then the general case of 3 <= N <= BOOST_PROTO_MAX_ARITY using the boost preprocessor. It seems to me that all cases could be handled uniformly (I'm not sure about the case for N=1, where you use display(proto::arg(expr)): is arg equivalent to arg_c<0>)? This part of debug.hpp seems also the likely cause of the problem I've mentioned in my other post (ambiguity when BOOST_PROTO_MAX_ARITY==2). It might be that the preprocessor iterates at least once anyhow, which might give a double definition for the case N==2 (why the generated item would correspond to the end of iteration rather than the beginning I don't know). It might be a bug in the preprocessor, but I don't know enough about what it is supposed to do. I also don't know why the case N==2 and N==3 below fail, as N==2 is handled as special case, (like N==1, which is ok) while N==3 is handled by preprocessor expansion of different code (like N==4, which is ok). #include <iostream> #include <boost/xpressive/proto/proto.hpp> #include <boost/xpressive/proto/context.hpp> #include <boost/xpressive/proto/extends.hpp> #include <boost/xpressive/proto/debug.hpp> #include <boost/typeof/typeof.hpp> #include <boost/typeof/std/ostream.hpp> namespace proto=boost::proto; struct udt_tag { friend std::ostream& operator << (std::ostream& os, const udt_tag o); unsigned int m_data; }; std::ostream& operator << (std::ostream& os, const udt_tag o) { os << "~" << o.m_data << "~"; return os; } struct udt_ex : proto::extends<proto::terminal<udt_tag>::type, udt_ex> { typedef proto::extends<proto::terminal<udt_tag>::type, udt_ex> expr_type; udt_ex () {} udt_ex (int i) : expr_type (expr_type::type::make (i)) {} using proto::extends<proto::terminal<udt_tag>::type, udt_ex>::operator=; }; int main (int, char**) { udt_ex b(3); display_expr (b*b(3,4,5,6)); // OK // display_expr (b*b(4,5,6)); // NOK: in proto/ref.hpp:72,73 forming reference to void // display_expr (b*b(5,6)); // NOK: in proto/ref.hpp:72,73 forming reference to void display_expr (b*b(6)); // OK b*b(3,4,5,6); // OK b*b(4,5,6); // OK b*b(5,6); // OK b*b(6); // OK }