Eri*_*ric 3 c++ casting operator-overloading
struct T {
int m_x;
T(int x) : m_x(x) {}
operator T() {
return T(0);
}
};
int main() {
volatile T v(2);
T nv(1);
nv = v; // nv.m_x = 0
}
Run Code Online (Sandbox Code Playgroud)
给出:
prog.cpp: In function ‘int main()’:
prog.cpp:14:10: error: no match for ‘operator=’ in ‘nv = v’
prog.cpp:14:10: note: candidates are:
prog.cpp:1:8: note: T& T::operator=(const T&)
prog.cpp:1:8: note: no known conversion for argument 1 from ‘volatile T’ to ‘const T&’
prog.cpp:1:8: note: T& T::operator=(T&&)
prog.cpp:1:8: note: no known conversion for argument 1 from ‘volatile T’ to ‘T&&’
Run Code Online (Sandbox Code Playgroud)
我需要定义什么类型转换重载才能正常工作?
您必须提供一种用户定义的转换方式才能启用此类分配。你可以
例:
X (X const volatile & xo);
X& operator= (X const volatile & xo);
Run Code Online (Sandbox Code Playgroud)
e当且仅当声明T t=e;的格式正确(对于某些发明的临时变量t(8.5))时,表达式才能隐式转换为T类型。
由于声明T t = e;(在这种情况下e为type volatile T)需要有效的复制初始化,因此您将需要来自volatile T的复制构造函数。
我已经回答了(为什么我没有从volatile提供默认的副本构造函数?)。因此,您需要提供一种用户定义的从volatile T复制T的方法。
X (X const volatile & xo);
Run Code Online (Sandbox Code Playgroud)
注意:
这将使您的作业工作。
使您的示例代码进行分配的另一种方法是复制分配运算符。
不幸的是,该标准还指出,编译器不会提供用于将易失性对象转换为非易失性对象的隐式副本分配运算符。
如果类定义没有显式声明一个副本分配运算符,则隐式声明一个。如果类定义声明了move构造函数或move赋值运算符,则隐式声明的副本赋值运算符将定义为Delete;否则,将其定义为默认值(8.4)。如果该类具有用户声明的副本构造函数或用户声明的析构函数,则不建议使用后一种情况。X类的隐式声明的副本赋值运算符将具有以下形式:
X&X :: operator =(const X&)
如果
- X的每个直接基类B都有一个副本分配运算符,其参数类型为const B&,const volatile B&或B,并且
- 对于类别类型为M(或其数组)的X的所有非静态数据成员,每个此类类别类型都有一个副本分配运算符,其参数类型为const M&,const volatile M&或M。122
否则,隐式声明的副本分配运算符将具有以下形式:
X&X :: operator = {X&)
隐式声明的副本分配运算符的引用参数不能绑定到易失性左值;参见C.1.9。
在另一个答案中,我引用了C.1.9:
隐式声明的副本构造函数和隐式声明的副本赋值运算符不能创建volatile左值的副本。[...]
结果是,如果我们想要一个副本赋值运算符,我们将不得不提供一个合适的副本赋值运算符。
X& operator= (X const volatile & xo);
Run Code Online (Sandbox Code Playgroud)
还要注意,您不能从volatile显式默认设置中声明分配/构造函数。
明确默认的功能应
- 是一个特殊的成员函数,
- 具有相同的声明函数类型(除了可能不同的ref限定符,以及对于复制构造函数或复制赋值运算符而言,参数类型可以是“对非常量T的引用”,其中T是成员函数的类),就好像它已隐式声明一样,并且
- 没有默认参数。
以下注释已从最终C ++ 11标准中删除,但已存在于N3242草案中。它仍然成立。
[注意:这意味着参数类型,返回类型和cv限定符必须与假设的隐式声明匹配。—尾注]
由于假设的隐式声明是非易失性的,因此您不能使用默认值。