
I apologize for the long post. It is probably too long for your holidays, I can wait. Eric Niebler <eric@boost-consulting.com> writes:
Maurizio Vitale wrote:
thanks, it sure helped a lot.
In my case I had to wrap proto::terminal inside a my_domain<> wrapper. This was required with the simplified code I posted, but I'm mentioning it for the benefit of others trying to learn proto.
Do you mean to say this was *not* required with the simple code you posted?
Indeed. I left the 'not' out, which unsurprisingly made my sentence meaningless.
I still have a couple of issues: - although udt_ex(v) is now parsed, udt_ex(v1,v2) is not.
The following program compiles for me. I suspect the problem you're seeing is not in proto.
#include <boost/xpressive/proto/proto.hpp> struct udt_tag {}; boost::proto::terminal<udt_tag>::type const udt = {{}}; int main() { udt(1,2); return 0; }
Not surprisingly your code compiles. A bit more surprisingly, mine now compiles as well. Here's what was happening: in my udt_ex I had a data member, and a constructor for initializing it. Hence no default constructor was generated. Adding a default constructor fixes this particular problem, but I understand from the rest of the mail that the place where I have my data is wrng to begin with.
I've tried
to #define BOOST_PROTO_MAX_ARITY to be 2, but this also doesn't seem to work (and if debug.hpp is included you get an ambiguous overload between debug.hpp:122 and rlocal.hpp:775.
I don't know what rlocal.hpp is. It is not a proto header. I suspect some other code you're including is interfering. I'm interested to see how.
rlocal.hpp is part of the boost preprocessor which you're using for generating the multiple overloads, so I suspect the conflict is between the same overload being generated more than once. I haven't investigated it further, though This is a short example that shows the problem (I'm using GCC 4.1.2) (ARITY 1 fails for different reasons) #define BOOST_PROTO_MAX_ARITY 2 #include <boost/xpressive/proto/proto.hpp> #include <boost/xpressive/proto/debug.hpp> struct udt_tag {}; boost::proto::terminal<udt_tag>::type const udt = {{}}; struct my_type : boost::proto::extends<boost::proto::terminal<udt_tag>::type, my_type> { my_type (int i) {}; my_type () {}; }; int main() { my_type x; x(1,2); return 0; } I'm also including the error message produced by the Intel compiler, in case you didn't have it: cd /home/mav/dev/proto_pdl/ /opt/intel/cce/9.1.046/bin/icpc -I. -o eric{,.cpp} ./boost/preprocessor/iteration/detail/rlocal.hpp(775): error: function template "void boost::proto::op::display_expr::operator()(const boost::proto::expr<Tag, Args, 2L> &) const" has already been declared BOOST_PP_LOCAL_MACRO(2) ^ eric.cpp(16): error: no instance of overloaded function "my_type::operator()" matches the argument list argument types are: (int, int) object type is: my_type x(1,2); ^
In my case udt contains additional data, not only extra methods and types. What is a good way for getting that information into the parse tree?
Put the data in udt_tag. Then rename udt_tag to udt_data or some such.
I'm not sure I understand, but since you ask later for my use case I'll describe it a bit more in detail. I'm trying to rewrite in terms of proto a library of numeric datatypes. The real thing will have all manners of fixed-point datatypes with limited and unlimited prescision, signed and unsigned representations w/ different encodings etc, but for the sake of simplicity, let's assume we have a single datatype that wraps an unsigned integer and that the only difference from a native integer is that we can specify a size in bit so that a limited number of bits is really used. template<unsigned int N> class my_int { my_int (unsigned int data) : m_data (data & (1U<<N - 1)) {} operator unsigned int () { return m_data; } my_int& operator= (unsigned int data) { m_data = data & (1U<<N - 1); } private: unsigned int m_data; }; The goal is to be able to write: my_int mi,mj; int i; 1) mi = mi + mj*2; 2) i = mj + mi; and delay the computation of the rhs until after optimizations have been performed. It seems to me that 1) should be doable by having a template<typename Expr> my_int& my_int::operator = (const Expr& e) that does optimization and evaluation in the appropriate context (for the small example here the default context would do). 2) seems doable by extending proto::expr in such a way that it offers an operator int() [and all other builtin types not covered by default promotions] Now my_int needs to be a type known to proto because it needs to be able to infect expressions. I was doing it by extending a tag, but this alone loses the reference to the data. If I understand your suggestion, m_data would go inside a my_int_tag structure, so now the parse tree contains the data and my_int would inherith from that so that its method can. Wouldn't then everything that is in my_int (data, methods typedef) go into the tag and my_int become an empty class inheriting from it (through the proto::extends mechanism which I presume causes at some point inheritance)? If so and the tag become a template, does proto::_ allow me to match all proto::terminal<my_int_tag< proto::_> > ? The lazy_vector example in the proto docs seems to do things a bit differently, but I still have to understand it fully.
Is specializing
as_expr going in the right direction? Basically, I'd like something like var/val in the lambda.cpp test, but without having to explicitly decorate expressions.
But you say above that you're already wrapping expressions. I'm confused. Maybe you could say a bit about your use case. Do you only want your udt terminals to have the extra data and members, or all expressions?
At the moment it seems that only terminals will require data members, but if the plan I outlined above is viable, expression will need additional methods (for converting to builtin and user-defined data types). So the reason I'm wrapping expression is to be able to add the appropriate conversion operators. Thanks for all the hand-holding during my first steps with proto. Regards, Maurizio