无法在成员函数中将左值绑定到右值,但在全局函数中可以
Can't bind lvalue to rvalue in member function but ok in global function
在查看 std::forward 的参考页时,我遇到了一些奇怪的事情。该示例将左值作为右值引用传递..但是传递给全局函数...它编译并运行。我尝试了与成员函数相同的操作,但无法编译。是什么赋予了?我希望在不使用 std::move
或 std::forward<T>
.
的情况下这两个调用都会失败
#include <iostream>
template <typename T>
void globalDoSomething(T &&data) {
std::cout << "We're doing it!!" << std::endl;
}
template <typename T>
class A {
public:
void doSomething(T &&data);
};
template <typename T>
void A<T>::doSomething(T &&data)
{
std::cerr << "Ah, man. I won't compile." << std::endl;
}
template class A<int>;
int main()
{
int b = 0;
globalDoSomething(b);
A<int> a;
a.doSomething(b);
return 0;
}
这是因为 globalDoSomething
的自动模板推导将 T
推断为 int&
。
如果像对模板的成员函数 class 那样用 globalDoSomething<int>(b);
显式实例化模板函数,它也会编译失败。
相反,如果用A<int&> a;
实例化模板class,它会成功编译。
致 build/add @Patrick Roberts 的回答,来自 template argument deduction
If P is an rvalue reference to a cv-unqualified template parameter
(so-called forwarding reference), and the corresponding function call
argument is an lvalue, the type lvalue reference to A is used in place
of A for deduction
简而言之,虽然 b
是左值,但它确实将 T
推断为 int&
。并且如示例所示
template<class T>
int f(T&& x) { // x is a forwarding reference
return g(std::forward<T>(x)); // and so can be forwarded
}
int main() {
int i;
f(i); // argument is lvalue, calls f<int&>(int&), std::forward<int&>(x) is lvalue
}
要对此进行测试,您可以设置一些不同类型的重载函数并检查
#include <iostream>
#include <utility>
void f(int&& x) {
std::cout << "rvalue reference overload f(" ")\n";
}
void f(const int& x) {
std::cout << "lvalue reference to const overload f(" ")\n";
}
void f(int& x) {
std::cout << "lvalue reference overload f(" ")\n";
}
template <typename T>
void globalDoSomething(T &&data) {
f(data);
}
int main()
{
int b = 0;
globalDoSomething(b);
return 0;
}
输出为
lvalue reference overload f()
在查看 std::forward 的参考页时,我遇到了一些奇怪的事情。该示例将左值作为右值引用传递..但是传递给全局函数...它编译并运行。我尝试了与成员函数相同的操作,但无法编译。是什么赋予了?我希望在不使用 std::move
或 std::forward<T>
.
#include <iostream>
template <typename T>
void globalDoSomething(T &&data) {
std::cout << "We're doing it!!" << std::endl;
}
template <typename T>
class A {
public:
void doSomething(T &&data);
};
template <typename T>
void A<T>::doSomething(T &&data)
{
std::cerr << "Ah, man. I won't compile." << std::endl;
}
template class A<int>;
int main()
{
int b = 0;
globalDoSomething(b);
A<int> a;
a.doSomething(b);
return 0;
}
这是因为 globalDoSomething
的自动模板推导将 T
推断为 int&
。
如果像对模板的成员函数 class 那样用 globalDoSomething<int>(b);
显式实例化模板函数,它也会编译失败。
相反,如果用A<int&> a;
实例化模板class,它会成功编译。
致 build/add @Patrick Roberts 的回答,来自 template argument deduction
If P is an rvalue reference to a cv-unqualified template parameter (so-called forwarding reference), and the corresponding function call argument is an lvalue, the type lvalue reference to A is used in place of A for deduction
简而言之,虽然 b
是左值,但它确实将 T
推断为 int&
。并且如示例所示
template<class T>
int f(T&& x) { // x is a forwarding reference
return g(std::forward<T>(x)); // and so can be forwarded
}
int main() {
int i;
f(i); // argument is lvalue, calls f<int&>(int&), std::forward<int&>(x) is lvalue
}
要对此进行测试,您可以设置一些不同类型的重载函数并检查
#include <iostream>
#include <utility>
void f(int&& x) {
std::cout << "rvalue reference overload f(" ")\n";
}
void f(const int& x) {
std::cout << "lvalue reference to const overload f(" ")\n";
}
void f(int& x) {
std::cout << "lvalue reference overload f(" ")\n";
}
template <typename T>
void globalDoSomething(T &&data) {
f(data);
}
int main()
{
int b = 0;
globalDoSomething(b);
return 0;
}
输出为
lvalue reference overload f()