
Boost : 
From: Eric Niebler (eric_at_[hidden])
Date: 20080407 13:51:03
Anthony Williams wrote:
> "Peter Dimov" <pdimov_at_[hidden]> writes:
>
>> Anthony Williams:
>>> "Peter Dimov" <pdimov_at_[hidden]> writes:
>>>
>>>> Eric Niebler:
>>>>
>>>>> Can you write what the identity function object would look like in
>>>>> C++0x?
>>>> struct identity
>>>> {
>>>> template<class A> A operator()( A && a ) const
>>>> {
>>>> return std::forward<A>( a );
>>>> }
>>>> };
>>>>
>>>> I guess.
>>> No. That will convert lvalues to rvalues.
>> Try it.
>
> I have, and it doesn't work. Besides, you can see in the signature: it returns
> "A" by value.
>
> You either need the overloads, or you need a trait class to correctly
> determine whether to return A or A&.
I'm afraid you're mistaken Anthony. The following program compiles and
runs with no errors on gcc4.3 with std=gnu++0x
#include <cassert>
#include <utility>
#include <type_traits>
struct identity
{
template<typename A>
A operator()(A && a) const
{
return std::forward<A>(a);
}
};
int main()
{
int i = 0;
int const j = 0;
// rvalue
static_assert(std::is_same<decltype(identity()(1)),
int>::value, "");
int k = identity()(1);
assert( 1 == k );
// lvalue
static_assert(std::is_same<decltype(identity()(i)), int
&>::value, "");
int &l = identity()(i);
assert( &l == &i );
// const lvalue
static_assert(std::is_same<decltype(identity()(j)), int const
&>::value, "");
int const &m = identity()(j);
assert( &m == &j );
}
Your confusion is probably due to the "special" rvalue deduction rule
that applies in function templates like this:
template<typename A>
A operator()(A && a)
When passed an lvalue int, A is actually deduced to be "int &". This is
in contrast with:
int operator()(int && a)
There is no deduction here, and so this would in fact force lvalues to
be rvalues.
 Eric Niebler Boost Consulting www.boostconsulting.com
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk