Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2005-05-11 16:50:04


Thorsten Ottosen wrote:
> "Peter Dimov" <pdimov_at_[hidden]> wrote in message
> news:004101c5566a$6aaecd50$6401a8c0_at_pdimov2...
>> Thorsten Ottosen wrote:
>>
>>> I don't know why you insists that we need two overloads.
>>>
>>> Given
>>>
>>> template< class T >
>>> MyType
>>> {
>>> Iter Begin();
>>> ConstIter Begin() const;
>>> ...
>>> };
>>>
>>> surely
>>>
>>> template< class T >
>>> auto begin( MyType<T>&& r ) -> decltype( r.Begin() )
>>> { return r.Begin(); }
>>>
>>> can handle both const and non-const arguments.
>>
>> No, it can't.
>
> do you care to explain why...I thought this was how we were supposed
> to solve the forwarding problem.

A forwarding function has a signature of the form

template<class T> auto begin( T && t );

When begin() is called on a const object, template argument deduction
deduces T as a const type.

X const x;

begin( x ); // T == X const &, T && == X const &

X const f();

begin( f() ); // T == X const, T && == X const &&

However, when you use MyType<T> &&:

template<class T> auto begin( MyType<T> && t );

MyType<int> const x;

begin( x ); // T == int

template argument deduction deduces T as int, and the attempt to bind
MyType<int>&& to x fails. An rvalue reference respects cv qualifiers, just
like an lvalue reference does.

You can try it with

template<class T> void begin( MyType<T> & t );

and see that it will fail in a similar way. Also try

template<class T> void begin( T & t );

to see that it will succeed and deduce T as MyType<int> const.

HTH.

As for the example in the paper:

std::if_< std::is_const<MyContainer>, const char*, char*>::type
begin( MyContainer&& c )
{
    return c.Begin();
}

since MyContainer is a specific non-const type, the compile-time if_ will
always return char*. begin() isn't even a template. You can't expect two
different return types from a single function.

char* begin( MyContainer& c )
{
    return c.Begin();
}

char const* begin( MyContainer const& c )
{
    return c.Begin();
}

Note that there is no need for an rvalue reference here unless you really
want to allow people to change a non-const rvalue in a for loop:

for( char& i: MyContainer() )
{
    ++i; // questionable
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk