Ben*_*ler 5 c++ templates c++11 move-assignment-operator
今天无意中发现了一段代码,我不明白。请考虑以下示例:
#include <iostream>
#include <string>
class A
{
public:
template <class Type>
Type& operator=(Type&& theOther)
{
text = std::forward<Type>(theOther).text;
return *this;
}
private:
std::string text;
};
class B
{
public:
B& operator=(B&& theOther)
{
text = std::forward<B>(theOther).text;
return *this;
}
private:
std::string text;
};
int main()
{
A a1;
A a2;
a2 = a1;
B b1;
B b2;
b2 = b1;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译时,MinGW-w64/g++ 10.2 指出:
..\src\Main.cpp: In function 'int main()':
..\src\Main.cpp:41:7: error: use of deleted function 'B& B::operator=(const B&)'
41 | b2 = b1;
| ^~
..\src\Main.cpp:19:7: note: 'B& B::operator=(const B&)' is implicitly declared as deleted because 'B' declares a move constructor or move assignment operator
19 | class B
| ^
mingw32-make: *** [Makefile:419: Main.o] Error 1
Run Code Online (Sandbox Code Playgroud)
我完全理解错误消息。但我不明白为什么我没有收到与 class 相同的消息A。模板化的移动赋值运算符不也是移动赋值运算符吗?那么为什么复制赋值运算符没有被删除呢?这段代码写得好吗?
作为对 @songyuanyao 基于标准的答案的补充:这些语言规则是 MISRA/AUTOSAR(安全关键型 C++ 开发语言指南)等指南的常见原因,以具有“避免开发人员混淆”规则,例如:
\n\n\n(来自AUTOSAR C++14 指南)
\n规则 A14-5-1(必需、实施、自动)
\n模板构造函数不应参与封闭类类型的单个参数的重载解析。\n
\n基本原理
\n模板构造函数永远不是复制或移动构造函数,因此\xe2\x80\x99不会阻止复制或移动构造函数的隐式定义,即使模板构造函数看起来相似并且可能\n很容易混淆。同时,复制或移动操作不一定只使用复制或移动构造函数,而是通过正常的重载解析过程来找到要使用的最佳匹配函数。在以下情况下这可能会导致混乱:
\n\n
\n- 未选择看起来像复制/移动构造函数的模板构造函数
\n- 对于复制/移动操作,因为编译器已生成隐式复制/移动构造函数,并且优先选择模板构造函数而不是复制/移动构造函数,因为\n模板构造函数更匹配
\n为了避免这些令人困惑的情况,模板构造函数不应参与封闭类类型的单个参数的重载解析,以避免为复制/移动操作选择模板构造函数。它还清楚地表明构造函数不是复制/移动构造函数,并且它不会阻止复制/移动构造函数的隐式生成。
\n规则 M14-5-3(必需、实施、自动)
\n当模板赋值运算符的参数是泛型参数时,应声明复制赋值运算符。
\n
也就是说,对于开发人员来说,模板复制/移动构造函数/赋值运算符不会抑制(/不“激活”5 规则)隐式生成的操作符,这可能会令人惊讶。您通常需要使用 SFINAE通过允许重载对封闭类的单个参数处于活动状态来确保模板化构造函数/赋值操作不会像复制/移动构造函数/赋值一样运行。
\n| 归档时间: |
|
| 查看次数: |
159 次 |
| 最近记录: |