
Thorsten Ottosen wrote:
"Peter Dimov" <pdimov@mmltd.net> wrote in message news:004101c5566a$6aaecd50$6401a8c0@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 }