
Hi Peter, "Peter Dimov" <pdimov@mmltd.net> wrote in message news:009201c55673$68a92330$6401a8c0@pdimov2... | 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. 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