Member function template with universal reference does not accept lvalues

I am trying to use a member function of a template to set a value inside my class. I wanted to use a universal reference so that I could accept any variant of the correct type (e.g. T , T& , T&& , const T , const T& , const T&& )

However, it looks like my member function will only accept rvalues, unlike a free function that accepts a universal reference.

 template <typename T> class Foo{ public: void memberURef(T&& t){ val = std::forward<T>(t); } private: T val; }; template <typename T> void freeURef(T&& t){ } int main() { int lval = 1; const int clval = 1; freeURef(lval); // fine freeURef(clval); // fine Foo<int> foo; foo.memberURef(2); foo.memberURef(lval); //error: cannot bind 'int' lvalue to 'int&&' foo.memberURef(clval); //error: no matching function for call to 'Foo<int>::memberURef(const int&)' return 0; } 
+3
c ++ c ++ 11 templates universal-reference
source share
1 answer

In the above code, Foo is created as Foo<int> . Once this happens, an instance template is created as shown:

 class Foo{ public: void memberURef(int&& t){ // Uh oh! val = std::forward<int>(t); } private: int val; }; 

Note how the member function is no longer a template and therefore no longer accepts a universal link, but an rvalue link. To create a member function that accepts a universal reference, the Foo class must be modified as follows:

 template <typename T> class Foo{ public: template <typename L> void memberURef(L&& t){ val = std::forward<L>(t); } private: T val; }; 

Thus, memberURef is still a function template after the instance template has been created, and thus it still accepts a universal reference.

+7
source share

All Articles