考虑这段C ++代码:
struct Foo {
float value;
operator float& () {
return this->value;
}
};
int main() {
Foo foo;
foo=1.0f; //Doesn't compile, foo isn't implicitly converted to a float&
return 0;
}
为什么不编译?是否有一个特定的原因,这不包括在C ++标准中?或者确实存在等价物,我只是错误使用它?
答案 0 :(得分:7)
对于几乎所有其他运营商而言,您的转换运营商将完全按照您的意愿行事,即使您添加自定义运营商,它也会继续完全按照您的意愿行事。
struct Foo {
float value;
operator float& () { return this->value; }
Foo &operator+=(Foo);
};
int main() {
Foo foo {};
foo+=1.0; // compiles and works
// equivalent to foo.operator float&()+=1.0;
}
但是,=
很特殊,=
的规则与大多数其他运营商相比有所不同。由T.C。确定:
13.3.1.2表达式中的运算符[over.match.oper]
4对于内置赋值运算符,左操作数的转换受到如下限制:
(4.1) - 没有引入临时值以保持左操作数,并且
(4.2) - 没有用户定义的转换应用于左操作数,以实现与内置候选的最左侧参数的类型匹配。
同时不允许将任何自定义operator=
定义为全局函数这一事实,这可确保foo=bar;
其中foo
是类类型始终意味着{{1没有别的。
这一运算符被挑选出来的事实并没有解释原因,但确实很明显这是一个有意的决定,并确保foo.operator=(bar);
总是意味着foo=bar;
,没有别的,它本身似乎已经是一个有效的理由。
答案 1 :(得分:6)
仅在以下情况下进行隐式转换:
只要某种类型的表达式执行隐式转换 T1用于不接受该类型的上下文中,但接受一些 其他类型T2;特别是:
- 当调用以T2为参数声明的函数时,将表达式用作参数;
- 当表达式用作操作数时,操作符需要T2;
- 初始化T2类型的新对象时,包括返回T2的函数中的return语句;
- 当表达式用在switch语句中时(T2是整数类型);
- 当表达式用于if语句或循环时(T2为bool)。
这里没有这种情况。相反,编译器正在尝试找到合适的operator=
来使用double
。要进行此编译,您需要重载该运算符(您实际上需要float
,如代码中所示):
Foo& operator=(float other)
{
value = f;
return *this;
}
并将您的作业更改为foo = 1.0f;
您的转化功能可以使用例如:
float f = foo;