|
Boost : |
From: Eric Niebler (eric_at_[hidden])
Date: 2008-04-07 13:09:46
Anthony Williams wrote:
> "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.
I don't understand why.
> You also need the lvalue overload in
> order to preserve the reference-ness of lvalues. IIRC, in Andrei
> Alexandrescu's talk at ACCU 2008 he also claimed you need a const-reference
> overload:
>
> struct identity
> {
> template<class A> A operator()( A && a ) const
> {
> return std::move( a );
> }
> template<class A> A& operator()( A & a ) const
> {
> return a;
> }
> template<class A> A const& operator()( A const & a ) const
> {
> return a;
> }
> };
>
> I'm not sure we need the third overload, as the second will deduce A to be
> "const A". Unfortunately, the only compiler I have which handles rvalue
> references says that the first two are ambiguous when given an lvalue.
If I were to write an identity that works today *and* tomorrow, I would
do it like this:
struct identity
{
// for C++03 compatibility
template<typename Sig>
struct result;
template<typename This, typename Arg>
struct result<This(Arg)>
{
typedef Arg type;
};
template<typename Arg>
Arg &operator()(Arg &arg) const
{
return arg;
}
template<typename Arg>
Arg const &operator()(Arg const &arg) const
{
return arg;
}
#if BOOST_HAS_RVALUE_REFS
template<typename Arg>
Arg operator()(Arg &&arg) const
{
return std::move(arg);
}
#endif
};
And now in both C++03 and C++0x, I can be sure the following code works:
int i = 0;
int const j = 0;
// rvalue
result_of<identity(int)>::type k = identity()(1);
assert( 1 == k );
// lvalue
result_of<identity(int &)>::type l = identity()(i);
assert( &l == &i );
// const lvalue
result_of<identity(int const &)>::type m = identity()(j);
assert( &m == &j );
As Giovanni points out, in C++0x "The values ti are lvalues when the
corresponding type Ti is a reference type, and rvalues otherwise."
So Peter, is this wrong?
-- 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