在右值引用简介中,提出了完美转发作为将右值 5 转发到具有非常量引用参数的构造函数的理想解决方案。
但是:
#include <memory>
#include <iostream>
#include <utility>
template <class T, class A1>
std::shared_ptr<T> factory(A1&& a1) {
return std::shared_ptr<T>(new T(std::forward<A1>(a1)));
}
class X {
public:
X(int& i){
std::cout<<"X("<<i<<")\n";
}
};
int main() {
std::shared_ptr<X> p = factory<X>(5);
}
在 XCode 4.2 和 G++ 4.6.1 中失败,没有已知的从 int 到 int& 的转换
,而:
template <class T, class A1>
std::shared_ptr<T> factory(A1&& a1) {
return std::shared_ptr<T>(new T(/*no forwarding*/a1));
}
编译。我做错了什么?
最佳答案
您不能将右值绑定(bind)到非常量左值引用。文章不建议为此使用完美转发,因为那是不可能的。完美转发将左值转发为左值,将右值转发为右值:
Here, forward preserves the lvalue/rvalue-ness of the argument that was passed to factory. If an rvalue is passed to factory, then an rvalue will be passed to T's constructor with the help of the forward function. Similarly, if an lvalue is passed to factory, it is forwarded to T's constructor as an lvalue.
由于您示例中的构造函数仅采用左值,因此您只能将左值传递给工厂函数。传递右值会将其作为右值转发,这将是格式错误的,因为无法将右值传递给该构造函数。
关于c++ - std::forward 和带有非常量引用参数的构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8355317/