Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2008-07-01 15:36:37


Eric Niebler wrote:
> 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.

8 overloads hurts compile times?

>> 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.

Understood

> 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.

Understood again. I don't get what you're driving at, though.

> 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.

Pretty much what I expected. Hm, what is poly_arg<T> ?

> 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.

All good things, although I think I contest point 3. It may be better,
but it can't be _as simple_ if you need poly_arg, template arguments,
and a poly_function wrapper.

>>>> 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 sorry if it sounded like you were being attacked; I was just trying
to find an explanation for the hurt you described in the context of my
understanding of the meaning of "const rvalue." Maybe where one really
gets hurt is in dealing with return values: if you treat const rvalues
as const lvalues you *will* dangle, and if you treat const lvalues as
const rvalues you will cause the wrong semantics in way too many common
cases.

> I'm letting users opt-in with reference_wrapper.

I understand that's the scope you chose. I was only trying to explore
whether that facility can usefully be pushed a little further so that we
don't lose move semantics inside of forwarded arguments. Well, I guess
we don't, if we assume everything's an rvalue by default :-)

-- 
Dave Abrahams
BoostPro Computing
http://www.boostpro.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk