bit*_*ise 6 c++ templates c++11 visual-studio-2012
我有这个代码,它不编译,这是预期的.
这是错误:an rvalue reference cannot be bound to an lvalue
class SomeData
{
public:
vector<int> data;
SomeData()
{
cout << "SomeData ctor" << endl;
data.push_back(1);
data.push_back(2);
data.push_back(3);
}
SomeData(const SomeData &other)
{
cout << "SomeData copy ctor" << endl;
data = other.data;
}
SomeData(SomeData &&other)
{
cout << "SomeData move ctor" << endl;
data = move(other.data);
}
~SomeData()
{
cout << "SomeData dtor" << endl;
}
void Print() const
{
for(int i : data)
cout << i;
cout << endl;
}
};
void Function(SomeData &&someData)
{
SomeData localData(someData);
localData.Print();
}
int main(int argc, char *argv[])
{
SomeData data;
Function(data); // ERROR
data.Print();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,当我Function()变成一个模板时,它工作正常,并使用复制构造函数SomeData.
template<class T>
void Function(T &&someData)
{
T localData(someData); // no more error
localData.Print();
}
Run Code Online (Sandbox Code Playgroud)
这是标准的C++行为吗?
我注意到视觉工作室在模板方面往往更宽容,所以我想知道我是否可以从所有兼容的C++ 11编译器中获得相同的行为.
是.在模板函数的情况下,编译器推导出模板参数T,使其与给定的参数匹配.
因为someData实际上是左值,T所以推断为SomeData &.Function类型扣除后的声明然后变成
void Function(SomeData & &&)
Run Code Online (Sandbox Code Playgroud)
并且SomeData & &&,遵循参考折叠规则,变为SomeData &.
因此,函数参数someData变为左值引用,并且这样传递给初始化localData.请注意(正如@aschepler正确指出的那样)localData被声明为T,因此它本身就是类型的引用SomeData &.因此,这里没有复制构造 - 只是初始化引用.
如果你想localData成为一个真正的副本,你必须将类型SomeData &转换为SomeData,即你必须&从类型中删除.你可以这样做std::remove_reference:
template<class T>
void Function(T &&someData)
{
/* Create a copy, rather than initialize a reference: */
typename std::remove_reference<T>::type localData(someData);
localData.Print();
}
Run Code Online (Sandbox Code Playgroud)
(为此,你必须这样做#include <type_traits>.)
| 归档时间: |
|
| 查看次数: |
808 次 |
| 最近记录: |