
Boost : 
From: Thorsten Ottosen (nesotto_at_[hidden])
Date: 20050512 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 nonconst 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 nonconst type, the compiletime 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 nonconst 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