C ++分配给隐式转换的左值

时间:2016-10-08 20:07:39

标签: c++ c++14

考虑这段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 ++标准中?或者确实存在等价物,我只是错误使用它?

2 个答案:

答案 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;