|
Boost : |
From: Eric Niebler (eric_at_[hidden])
Date: 2008-04-07 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 gcc-4.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.boost-consulting.com
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk