Boost logo

Boost :

From: Thorsten Ottosen (nesotto_at_[hidden])
Date: 2005-05-12 14:35:25


Hi Peter,

"Peter Dimov" <pdimov_at_[hidden]> wrote in message
news:009201c55673$68a92330$6401a8c0_at_pdimov2...
| 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.

hm..you learn something new every day; I wasn't aware of the difference
between T& and UDT<T>&

| 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
| }

it seems to be very useful if you're chaining algorithms that all acts on
rvalues.

still, we need two version of each function, the && version and the const &
version.

I wish we didn't.

-Thorsten


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