
Peter Dimov wrote:
Eric Niebler:
make_plus is trickier. It must be optimal and safe. When passed lvalues, it should return a new node that holds the children by reference. When passed rvalues, it should return a new node that hold the children by value.
== Problem ==
Here's the thing ... I have no idea how to implement make_plus as a TR1 function object.
I think that you are right; you can't implement make_plus as a C++03 function object. result_of is a red herring. The missing part is &&, not decltype (which result_of is supposed to approximate).
Right!
You can do this:
struct make_plus { template<typename Sig> struct impl;
template<typename This, typename Left, typename Right> struct impl< This(Left, Right) > { // Left and Right are allowed to be reference types typedef plus<Left, Right>::type result_type;
result_type operator()( typename add_const_ref<Left>::type left ,typename add_const_ref<Right>::type right ) const { return result_type(left, right); } }; };
but it's not a function object.
Correct. However, I can do this: struct make_plus : function_adaptor<make_plus> { // same as before }; where function_adaptor implements the TR1 function object protocol and makes some guess about const-ref arguments -- probably that they are rvalues. It could even implement the reference_wrapper gunk to treat reference_wrapper<X> arguments as if they were X&. This is the route Proto is taking. Proto can query a function object F if it uses this protocol and use it if it's available, getting correct lvalue/rvalue handling. If it's not available, it uses result_of, stripping references from argument types first. I think I got the idea from reading through Egg's documentation. It seems like if this sort of thing doesn't exist there, it probably should. Shunsuke? -- Eric Niebler Boost Consulting www.boost-consulting.com