多参数隐式转换、运算符重载

Implicit conversion with more than one parameter, and operator overloading

我正在阅读 "The C++ Programming Language" 本书。下面是相关代码

class complex {
public:
  complex(double r, double i): re{r}, im{i} {}
  complex(double r): complex{r,0} {}
  complex(): complex{0,0} {}

  complex& operator-=(complex z) {
    this->re -= z.re;
    this->im -= z.im;
    return *this;
  } 
private:
  double re,im;
};

inline complex operator-(complex a, complex b) {
  return a -= b;
}

inline complex operator-(complex z) {
  return{ 0, 0 } - z;
}

一元operator-报错-

syntax error : missing ';' before '-'

但是,编译器认为以下两种变体都是正确的

inline complex operator-(complex z) {
  return 0 - z;
}

inline complex operator-(complex z) {
  return {-z.real(), -z.imag()};
}

我认为在这两种情况下都会发生隐式转换。 那为什么是

inline complex operator-(complex z) {
  return {0,0} - z;
}

标记为错误?

编辑 - 修复 return 类型的 operator-= 函数调用,并添加 operator-(),因为它与问题相关。

我假设教科书中的示例也提供了一个二进制 operator-,因为没有它,即使 {0, 0} 被隐式转换为 complex,代码也无法编译违规行。

return{ 0, 0 } - z;

此行无法编译的原因是 braced-init-list ({0, 0}) 不是表达式,因此没有类型。所以它不能用作二进制 operator-.

的操作数之一

return {-z.real(), -z.imag()}; 起作用的原因是标准明确允许它。

§6.6.3/2 [stmt.return]

The expression or braced-init-list of a return statement is called its operand. ... A return statement with any other operand shall be used only in a function whose return type is not cv void; the return statement initializes the object or reference to be returned by copy-initialization (8.5) from the operand.

本例中的复制初始化复制列表初始化§8.5.4 [dcl.init.list]) 并且它会考虑 complex(double r, double i) 构造函数,因为它不是 explicit.


operator-=的return类型也很奇怪,它修改了complex实例,但是return是一个副本。一个典型的实现是

complex& operator-=(complex const& z) {
...
}