问题
I've been trying to use a template member function to set a value inside of 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 seems that my member function will only accept rvalues, unlike a free function accepting 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;
}
回答1:
In the code given, Foo
is instantiated as Foo<int>
. Once this happens, the class template is instantiated as shown:
class Foo{
public:
void memberURef(int&& t){ // Uh oh!
val = std::forward<int>(t);
}
private:
int val;
};
Notice how the member function is no longer a template, and therefore no longer accepts a universal reference, but an rvalue reference. In order to make a member function that accepts a universal reference, the Foo
class would need to 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;
};
That way, memberURef
is still a function template after the class template has been instantiated, and it thus still accepts a universal reference.
来源:https://stackoverflow.com/questions/28643645/member-function-template-with-universal-reference-wont-accept-lvalues