
David Abrahams wrote:
Eric Niebler wrote:
-- snip 2^10 overloads --
Yeah, that's probably too much, but I'm not sure we have to support forwarding for that many arguments. The only thing rvalue forwarding buys you (and it can be a big win) is the ability for the wrapped thing to make certain optimizations. It's a good idea when you can do it. If you can't do it, you can fall back to lvalues and in C++03 you've still done a credible job.
Even 2^3 overloads has a *very* noticeable effect on compile times.
Can you show me an example of a "sound" function that treats a const rvalue differently from an lvalue, please? fusion::make_vector(), for instance. It returns a fusion::vector<> where
David Abrahams wrote: the members can be held by value or by reference. Getting it wrong can lead to dangling references. Proto has similar function objects that need to be careful about the lifetime of temporaries.
I'm a little confused.
Proper rvalue detection for *wrapper functions* or not, we have no way of writing make_vector so that it stores all rvalues and references lvalues. So in C++03, that function needs some hints about when to store values.
Of course.
I'm not convinced it doesn't need those hints in C++0x.
Right.
After all, any time you build a vector of references from lvalues, those references (or copies thereof) can be made to dangle.
That doesn't mean a wrapper function should not forward non-const rvalues to its wrapee.
The wrapper I wrote (poly_function) passes arguments to the wrapped function and also passes along information about whether the user specified that argument as an lvalue (reference-wrapped) or not. That's all. Whether the wrapped function *actually* accepts its (rvalue) arguments as "T" or "T const &" is a different issue. poly_function doesn't care. When you use poly_function, you basically write a template that generates mono-morphic function objects like this: template< class Arg0, class Arg1 > struct my_function { typedef ... result_type; result_type operator()(poly_arg<Arg0> a0, poly_arg<Arg1> a1) const { ... } }; If ArgN is a reference, then the user has reference-wrapped the argument. If it isn't a reference, it was passed unwrapped. What poly_function buys you is: 1) It implements the result_of protocol for you, correctly handling const, refs, and reference wrappers. 2) It unwraps any reference wrapped args before forwarding them. 3) It makes writing a polymorphic function object as simple as writing a monomorphic one.
It wouldn't be useful for my purposes. What I took from the discussion about result_of and C++03 was that, for a function object that cares about lvalue/rvalue-ness to work consistently across C++03 and C++0x, assuming rvalue-ness and opting in for lvalue-ness with reference_wrapper<> is really the only option. But if you have an insight, I'd be happy to reopen that discussion. It was rather unsatisfying last time. I just think that since you don't have permission to mutate a const rvalue anyway, forwarding it as a const reference doesn't really hurt anyone. When I've gotten it wrong, it hurts.
Maybe you're making assumptions that you really can't afford to make (that storing a reference to an lvalue, even when properly detected, is a good idea).
Please, I'm not trying to detect lvalue/rvalue-ness! I'm letting users opt-in with reference_wrapper. -- Eric Niebler BoostPro Computing http://www.boostpro.com