Boost logo

Boost :

From: Howard Hinnant (hinnant_at_[hidden])
Date: 2008-04-08 20:49:36

Forwarded on behalf of and request of Andrei Alexandrescu


Begin forwarded message:
> Howard Hinnant wrote:
>> On Apr 8, 2008, at 12:12 PM, Eric Niebler wrote:
>>> There is some confusion on the Boost list about the behavior of
>>> rvalue references, caused in part by Andrei's ACCU keynote. Can one
>>> of you clear up the issue of the proper way to define the
>>> "identity" function in C++0x? Thanks.
>> I haven't read through this entire thread, mainly because I don't
>> have
> any practical applications for identity at the moment. The simplest
> version I can think of is:
>> template <class T> T identity(T&& t) {return std::forward<T>(t);}
> // or return static_cast<T&&>(t)
>> Sorry Andrei, I didn't think of this one before your talk.
>> All cv-qualifiers of the argument are deduced into T. If the
>> argument
> is an lvalue A, T is deduced as A&, and an lvalue is returned. In
> this case, forward (or static_cast) is a no-op. If the argument is an
> rvalue A, T is deduced as A, and an rvalue is returned (by value). In
> this case forward (or static_cast) "casts" the lvalue t to an rvalue
> simply for the purpose of efficiently moving a heavy type to return by
> value. This also reduces the requirements on an rvalue T from
> CopyConstructible to only MoveConstructible.
>> If you don't want to return by value in the case of an rvalue, then
> you could also:
>> template <class T> T&& identity(T&& t) {return t;}
>> For lvalues, this behaves the same as above. For rvalues you now
> return by rvalue reference instead of by value. If the client catches
> this rvalue reference by reference, that reference will be dangling:
>> const A& acr = identity(A()); // acr now points to a destructed A
>> That may or may not be acceptable for the use cases of identity. I
> have no idea what those use cases are.
> The identity function is not to be used per se; it only gauges to what
> extent a value transports its type information. For example, if
> identity
> works properly, min and max should be easy. Inspired by your
> solution, I
> tried this with conceptg++:
> template <class T, class U>
> decltype(true ? T() : U()) Min(T&& a, U&& b) {
> return b < a ? b : a;
> }
> Given that your implementation of identity works, then the above
> should
> work as well by always properly depositing the type of the incoming
> expressions in T and U whether they are lvalues, const lvalues, or
> rvalues.
> However, the implementation above doesn't work due to what I hope is a
> compiler bug. The calls:
> int a, b;
> int & f = Min(a, b);
> int g = Min(a + 1, 42);
> work, but this won't:
> int g = Min(a, 42);
> The error message says:
> error: operands to ?: have different types int& and int
> But ?: should work with int& and int, yielding int (as needed).
> Andrei

Boost list run by bdawes at, gregod at, cpdaniel at, john at