[Proto] Storing an Expression Template as a Data Member

Dear all, Is there any way I can have classes with data members of type (proto) expression templates? Here is where I get stuck: template<typename T> class MyClass { ... T expression_; }; What type should T be? If you're wondering why on earth I might need that, here is an explanation: Instances of MyClass need to store the lazy calculation they will be performing later on when enough initialisation data is available. Each instance of MyClass has its own FORMULATION for the lazy calculation in terms of the initialisation data. They need to be fed with these formulations and I thought (proto) expression templates will perhaps do the job. But, then, I don't know how to store these formulations until it's time for them to perform... TIA, --Hossein

On 1/6/2011 8:58 AM, Hossein Haeri wrote:
Dear all,
Is there any way I can have classes with data members of type (proto) expression templates? Here is where I get stuck:
template<typename T> class MyClass { ... T expression_; };
What type should T be?
If you're wondering why on earth I might need that, here is an explanation: Instances of MyClass need to store the lazy calculation they will be performing later on when enough initialisation data is available. Each instance of MyClass has its own FORMULATION for the lazy calculation in terms of the initialisation data. They need to be fed with these formulations and I thought (proto) expression templates will perhaps do the job. But, then, I don't know how to store these formulations until it's time for them to perform...
If you use proto::make_expr to build expressions explicitly (instead of using the operator overloads), you can have completel control over how sub-expressions are stored. (You'll need them to be stored by value if you're saving the ET in a variable; otherwise, they'll go out of scope.) And if you're using proto::make_expr, you can use proto::result_of::make_expr to compute the type of the resulting ET. Read the docs for make_expr carefully. That should solve your problem. HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com

Dear Eric, I will certainly have another read over make_expr. But, I have a feeling that I might not have explained what I need very well. So, with some connection to the function streaming thing we were in contact on previous threads, here is an example: MyClass mc(_1 >> &f >> &g >> &h); mc.set_input(-61.1); cout << mc.value();//returns h(g(f(-61.1))) Now, are you telling me that I can store that "_1 >> &f >> &g >> &h" bit in a data member of mc using make_expr? If so, what will the type of that data member be? Or, are you suggesting a totally different design? TIA, --Hossein --- On Thu, 6/1/11, Eric Niebler <eric@boostpro.com> wrote:
Dear all,
Is there any way I can have classes with data members of type (proto) expression templates? Here is where I get stuck:
template<typename T> class MyClass { ... T expression_; };
What type should T be?
If you're wondering why on earth I might need that, here is an explanation: Instances of MyClass need to store the lazy calculation they will be performing later on when enough initialisation data is available. Each instance of MyClass has its own FORMULATION for the lazy calculation in terms of the initialisation data. They need to be fed with these formulations and I thought (proto) expression templates will perhaps do the job. But, then, I don't know how to store these formulations until it's time for them to
From: Eric Niebler <eric@boostpro.com> Subject: Re: [Boost-users] [Proto] Storing an Expression Template as a Data Member To: boost-users@lists.boost.org Date: Thursday, 6 January, 2011, 16:10 On 1/6/2011 8:58 AM, Hossein Haeri wrote: perform...
If you use proto::make_expr to build expressions explicitly (instead of using the operator overloads), you can have completel control over how sub-expressions are stored. (You'll need them to be stored by value if you're saving the ET in a variable; otherwise, they'll go out of scope.)
And if you're using proto::make_expr, you can use proto::result_of::make_expr to compute the type of the resulting ET.
Read the docs for make_expr carefully. That should solve your problem.
HTH,
-- Eric Niebler BoostPro Computing http://www.boostpro.com _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

2011/1/6 Hossein Haeri <powerprogman@yahoo.com>
Dear Eric,
I will certainly have another read over make_expr. But, I have a feeling that I might not have explained what I need very well. So, with some connection to the function streaming thing we were in contact on previous threads, here is an example:
MyClass mc(_1 >> &f >> &g >> &h); mc.set_input(-61.1); cout << mc.value();//returns h(g(f(-61.1)))
Now, are you telling me that I can store that "_1 >> &f >> &g >> &h" bit in a data member of mc using make_expr? If so, what will the type of that data member be? Or, are you suggesting a totally different design?
This is not possible in C++. It becomes possible if you specify the type of the argument: MyClass<double> mc(...); Now mc.set_input can only be called with double. Roman Perepelitsa.

2011/1/6 Roman Perepelitsa <roman.perepelitsa@gmail.com>
2011/1/6 Hossein Haeri <powerprogman@yahoo.com>
Dear Eric,
I will certainly have another read over make_expr. But, I have a feeling that I might not have explained what I need very well. So, with some connection to the function streaming thing we were in contact on previous threads, here is an example:
MyClass mc(_1 >> &f >> &g >> &h); mc.set_input(-61.1); cout << mc.value();//returns h(g(f(-61.1)))
Now, are you telling me that I can store that "_1 >> &f >> &g >> &h" bit in a data member of mc using make_expr? If so, what will the type of that data member be? Or, are you suggesting a totally different design?
This is not possible in C++.
I take it back :-) It *is* possible if the expression involves only functions and no function objects. Roman Perepelitsa.

On 1/6/2011 11:39 AM, Hossein Haeri wrote:
Dear Eric,
I will certainly have another read over make_expr. But, I have a feeling that I might not have explained what I need very well. So, with some connection to the function streaming thing we were in contact on previous threads, here is an example:
MyClass mc(_1 >> &f >> &g >> &h); mc.set_input(-61.1); cout << mc.value();//returns h(g(f(-61.1)))
Now, are you telling me that I can store that "_1 >> &f >> &g >> &h" bit in a data member of mc using make_expr? If so, what will the type of that data member be? Or, are you suggesting a totally different design?
Ah. That part (the usage) wasn't clear. No, you can't use it like that. I would suggest transforming the expression into a unary function object (see my article on cpp-next.com about function composition), and be sure your transform also stores everything by value. (Or pass everythying through deep_copy.) Then store the resulting unary function in a boost::function, so it's type-erased. HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com

Hi Eric,
MyClass mc(_1 >> &f >> &g >> &h); mc.set_input(-61.1); cout << mc.value();//returns h(g(f(-61.1)))
Here is my solution: template<typename Expr> struct MyClass { MyClass(const Expr& e): formula_(e) {} double calculate(double d) const {return evaluate(formula_, d);} private: const Expr formula_;//*** }; #define DEFINE_MY_CLASS(name, exp) MyClass<BOOST_TYPEOF(exp)> name(exp) ... So that my customers can say: DEFINE_MY_CLASS(mc, _1 >> &f >> &g >> &h); cout << mc.calculate(-6.1);//prints h(g(f(-61.1))) Does the fact that I store formula_ by value (as in line ***) shoot the trouble of dangling references?
I would suggest transforming the expression into a unary function object (see my article on cpp-next.com about function composition),
I do follow that series of yours and have to say it's superb! :) I don't see how that's connected though. So, if you think your suggested solution above would be better than that of mine, I'd be more than happy to see more explanation. Specifically, what are you exactly referring to when you use the term "expression" above? And, leave it if you'd think my solution is good enough... :D TIA, --Hossein

On 1/6/2011 6:48 PM, Hossein Haeri wrote:
Hi Eric,
MyClass mc(_1 >> &f >> &g >> &h); mc.set_input(-61.1); cout << mc.value();//returns h(g(f(-61.1)))
Here is my solution:
template<typename Expr> struct MyClass { MyClass(const Expr& e): formula_(e) {} double calculate(double d) const {return evaluate(formula_, d);} private: const Expr formula_;//*** };
#define DEFINE_MY_CLASS(name, exp) MyClass<BOOST_TYPEOF(exp)> name(exp) ...
So that my customers can say:
DEFINE_MY_CLASS(mc, _1 >> &f >> &g >> &h); cout << mc.calculate(-6.1);//prints h(g(f(-61.1)))
Does the fact that I store formula_ by value (as in line ***) shoot the trouble of dangling references?
No, the problem still exists. You're storing the outer-most node by value, but all the inner nodes (temporary objects constructed while building the expression) are held by reference. At the very least, the constructor of MyClass needs to pass the incoming expression through deep_copy.
I would suggest transforming the expression into a unary function object (see my article on cpp-next.com about function composition),
I do follow that series of yours and have to say it's superb! :) I don't see how that's connected though.
That article takes a sequence of function calls and turns them into a single callable object. You're taking a sequence of function calls and are turning them into a callable object.
So, if you think your suggested solution above would be better than that of mine, I'd be more than happy to see more explanation. Specifically, what are you exactly referring to when you use the term "expression" above? And, leave it if you'd think my solution is good enough... :D
Pros and cons. The solution I had in mind didn't involve the preprocessor or Boost.Typeof which (on some platforms) is a real, ugly hack. (But a very useful one, I must admit.) The solution I was suggesting is more work and would have slightly worse runtime performance ... type-erasure always involves an indirection somewhere. It's really a judgment call. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Hi Eric,
Does the fact that I store formula_ by value (as in line ***) shoot the trouble of dangling references?
No, the problem still exists. You're storing the outer-most node by value, but all the inner nodes (temporary objects constructed while building the expression) are held by reference. At the very least, the constructor of MyClass needs to pass the incoming expression through deep_copy.
So, what about the following? #define DEFINE_MY_CLASS(name, exp) \ MyClass<result_of::deep_copy<BOOST_TYPEOF(exp)>::type> name(deep_copy(exp))
That article takes a sequence of function calls and turns them into a single callable object. You're taking a sequence of function calls and are turning them into a callable object.
I see. OK, so you're basically saying that the >> syntax can be avoided and that we can use simple function object composition instead with no need for Protofication. In that case, I need to say that this >> syntax is just a part of the larger syntax which fits very naturally to the application I'm developing for. Thanks a lot. :) --Hossein

On 1/8/2011 9:06 AM, Hossein Haeri wrote:
Hi Eric,
Does the fact that I store formula_ by value (as in line ***) shoot the trouble of dangling references?
No, the problem still exists. You're storing the outer-most node by value, but all the inner nodes (temporary objects constructed while building the expression) are held by reference. At the very least, the constructor of MyClass needs to pass the incoming expression through deep_copy.
So, what about the following?
#define DEFINE_MY_CLASS(name, exp) \ MyClass<result_of::deep_copy<BOOST_TYPEOF(exp)>::type> name(deep_copy(exp))
Sure. Or you could move the deep-copy action an implementation detail of MyClass and keep the macro simple. Whichever.
That article takes a sequence of function calls and turns them into a single callable object. You're taking a sequence of function calls and are turning them into a callable object.
I see. OK, so you're basically saying that the >> syntax can be avoided and that we can use simple function object composition instead with no need for Protofication.
No, I'm not saying that. I'm saying you can use >> and Proto to build an expression tree, and use a transform to compose that tree into a function object. But the principles of that transformation are the same as what's described in the article. Once you have the composed function as a function object, you can store it in a boost::function. -- Eric Niebler BoostPro Computing http://www.boostpro.com

So, what about the following?
#define DEFINE_MY_CLASS(name, exp) \
MyClass<result_of::deep_copy<BOOST_TYPEOF(exp)>::type> name(deep_copy(exp))
Sure. Or you could move the deep-copy action an implementation detail of MyClass and keep the macro simple. Whichever.
Right. Either way, how should I deal with copy construction? Is the deeply copied thing automatic for copy construction? Or, should I make another deep copy each time?
No, I'm not saying that. I'm saying you can use >> and Proto to build an expression tree, and use a transform to compose that tree into a function object. <snip>
I see. Hmmm... I guess the same technique wouldn't be working uniformly for my entire syntax. Thanks for the suggestion though. :)

On 1/8/2011 1:55 PM, Hossein Haeri wrote:
So, what about the following?
#define DEFINE_MY_CLASS(name, exp) \
MyClass<result_of::deep_copy<BOOST_TYPEOF(exp)>::type> name(deep_copy(exp))
Sure. Or you could move the deep-copy action an implementation detail of MyClass and keep the macro simple. Whichever.
Right. Either way, how should I deal with copy construction? Is the deeply copied thing automatic for copy construction? Or, should I make another deep copy each time?
A Proto expression that has been passed through proto::deep_copy owns all its sub-objects. The default copy constructor should just do the right thing.
No, I'm not saying that. I'm saying you can use >> and Proto to build an expression tree, and use a transform to compose that tree into a function object. <snip>
I see. Hmmm... I guess the same technique wouldn't be working uniformly for my entire syntax. Thanks for the suggestion though. :)
Not sure I see what the problem is. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Hi Eric,
Right. Either way, how should I deal with copy construction? Is the deeply copied thing automatic for copy construction? Or, should I make another deep copy each time?
A Proto expression that has been passed through proto::deep_copy owns all its sub-objects. The default copy constructor should just do the right thing.
So, do I understand it correctly that there won't be any double-deletion in the following code: auto ex1 = lit(1) + 3; { auto ex2 = ex1; } ex2 will copy everything in ex1, right? (OK, except for function references.) Thanks, --Hossein

On 1/9/2011 5:56 PM, Hossein Haeri wrote:
Hi Eric,
Right. Either way, how should I deal with copy construction? Is the deeply copied thing automatic for copy construction? Or, should I make another deep copy each time?
A Proto expression that has been passed through proto::deep_copy owns all its sub-objects. The default copy constructor should just do the right thing.
So, do I understand it correctly that there won't be any double-deletion in the following code:
auto ex1 = lit(1) + 3;
Don't EVER do this. It will leave dangling references to intermediate nodes for all the same reasons that I've given before. If you want to store an expression in a variable, you MUST pass it through deep_copy. Do this: auto ex1 = proto::deep_copy( lit(1) + 3 );
{ auto ex2 = ex1; }
ex2 will copy everything in ex1, right? (OK, except for function references.)
Right. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Hi Eric,
auto ex1 = lit(1) + 3;
Don't EVER do this.
Oops! Out of habit; I currently don't use C++0x and therefore do that using BOOST_PROTO_AUTO -- not used to using deep_copy thus...
auto ex1 = proto::deep_copy( lit(1) + 3 );
{ auto ex2 = ex1; }
ex2 will copy everything in ex1, right? (OK, except for function references.)
Right.
Cool. Then, I suggest that you do make this (more) clear in the Proto docs. Maybe you'd even like to add a subsection on how to store Proto expressions as data members and then also include a note on the sufficiency of default copy constructors. Thanks, --Hossein

2011/1/7, Hossein Haeri <powerprogman@yahoo.com>:
MyClass mc(_1 >> &f >> &g >> &h); mc.set_input(-61.1); cout << mc.value();//returns h(g(f(-61.1)))
Now, are you telling me that I can store that "_1 >> &f >> &g >> &h" bit in a data member of mc using make_expr? If so, what will the type of that data member be? Or, are you suggesting a totally different design?
Hi, Hossein. IIUC, you may need some way to abstract the ET away, maybe by using boost::function, like what Spirit does for its rule component. Is this what you want?
participants (4)
-
Eric Niebler
-
Hossein Haeri
-
Roman Perepelitsa
-
TONGARI