
Boost : 
From: Eric Niebler (eric_at_[hidden])
Date: 20080701 18:24:05
David Abrahams wrote:
>
> I think it's maybe better illustrated as
>
> template <class F, class T>
> result_of<F(T&)>::type
> forwarder(F const& g, T& x);
>
> If g(x) returns an rvalue, forwarder had better also return an rvalue
> or the result will dangle. if g(x) returns a const lvalue and forwarder
> does not, you can get silent odd behavior when the value returned from
> forwarder turns out to be a different object from the one g(x)
> references. Such functions can only work right if result_of returns the
> proper "referenceness."
Correct. And the question raised in the "result_of and C++03" thread
was: is the "referenceness" of of result_of<F(T&)>::type allowed to be
influenced by the "referenceness" of the arguments in the function
type. That is, what do these mean, are they different and if so, how?
result_of<F(T)>::type // 1
result_of<F(T&)>::type // 2
result_of<F(T const&)>::type // 3
There be dragons there in C++03 because there's no way in C++03 to
overload a function on T, T& and T const&. The only workable solution
I've found so far is that these all mean the same thing: the result of
calling F with an rvalue of type T, unless T is a reference_wrapper<U>,
in which case, it's the result of calling F with an lvalue of type U.
If your reaction is "yuk" then I agree, but I haven't yet thought of
something better. Now, you might say that we can detect case (2) in
C++03 and make it mean "lvalue of type T", but for functions that take N
arguments, that leads us to 2^N overloads, and 2^N return type
calculations, which I'm trying to avoid.
> However, there's no problem AFAICS with a forwarder like this, if it
> could be implemented.
>
> // Madeup syntax follows
>
> template <class F, class T>
> decltype(g(x))
> forwarder(F const& g, T& x) if (x is an lvalue or const rvalue)
> {
> g( x );
> }
>
>
> template <class F, class T>
> decltype(g(move(x)))
> forwarder(F const& g, T x) if (x is a nonconst rvalue)
> {
> g( move(x) );
> }
>
> for any sane implementation of F. That's my only point. It's not a big
> deal that we can't tell const rvalues from const lvalues where function
> arguments are concerned.
Hm, I *think* I get it.
>>>> I'm letting users optin 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 :)
>> I'm not sure if changes are needed to better support move semantics, or
>> what they would be. Feedback is welcome.
>
> Basically, if your wrappers copy arguments by default,
They don't. They could, but I don't think they should, do you?
> then it's always
> safe for wrapped functions to move from arguments unless they are
> reference_wrappers. We could even make move(x) where x is a
> reference_wrapper return an lvalue, so it'd be transparent.
I'm not seeing a win here, at least not for C++03. Little help?
 Eric Niebler 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