为什么大多数默认运算符不能有占位符返回类型,即 auto?

Why can't most defaulted operators have a placeholder return type, i.e. auto?

提问人:Jan Schultke 提问时间:9/13/2023 更新时间:9/13/2023 访问量:66

问:

C++20 使默认比较运算符成为可能,包括像这样的三向比较。 可以具有推导的返回类型,但其他运算符不能:<=>

struct S {
    friend auto operator<=>(const S&, const S&) = default; // OK
    friend auto operator==(const S&, const S&) = default;  // error, return type must be bool
    auto& operator=(const S&) = default;                   // error, return type must be S&
};

存在此限制的原因是什么?感觉很武断。 唯一可以合理推断为 for 的返回类型是 。autooperator==bool


注意:这是一个 wiki 风格的问答,其主要目标是提高对限制性语言设计和旨在解决它的 提案的认识。

++26 c ++ 语言设计 return-type-deduction defaulted-functions

评论


答:

2赞 Jan Schultke 9/13/2023 #1

该限制纯粹是历史性的,假设 auto& operator=(X&&) = default 被接受为标准P2952R0它很有可能在 C++26 年被取消。

从提案中:

auto& operator=(const MyClass& rhs) { i = rhs.i; return *this; } // well-formed
auto& operator=(const MyClass& rhs) = default; // ill-formed, must say 'MyClass&'

auto operator==(const MyClass& rhs) const { return i == rhs.i; } // well-formed
auto operator==(const MyClass& rhs) const = default; // ill-formed, must say 'bool'

这些声明的格式错误来自标准中过于严格的措辞,例如 [class.eq]/1 明确要求默认相等运算符必须具有声明的返回类型 ,而不是简单地指定其返回类型必须为 。我们认为上面的每个示例都有一个直观清晰的含义:占位符返回类型与默认正文实际返回的类型正确匹配。我们建议放宽目前的限制,并允许这些声明的格式正确。boolbool

从本质上讲,该提案将使推导的返回类型在预期特定返回类型的情况下有效。它不会更改有效返回类型的集。

实施挑战和边缘案例

值得注意的是,当涉及到有效返回类型集时,编译器存在一些分歧。例如

// only clang rejects this, other compilers allow it
friend bool operator==(const C, const C) = default;

但是,这种分歧不应该妨碍提案,因为它提出了“规范”返回类型:

默认的二级比较运算符函数应具有返回类型。如果其声明的返回类型包含占位符类型,则其返回类型将推断为 from 。boolreturn true;

评论

0赞 Barry 11/14/2023
这种“边缘情况”与返回类型无关(该函数非常返回),而是与参数类型有关 - 因为参数需要两者或两者兼而有之(而不是两者)。我不确定为什么其他实现允许它,因为要么添加 s(以避免复制)要么删除 s(因为它们毫无意义?boolCC const&C const&const