提问人:Jan Schultke 提问时间:9/13/2023 更新时间:9/13/2023 访问量:66
为什么大多数默认运算符不能有占位符返回类型,即 auto?
Why can't most defaulted operators have a placeholder return type, i.e. auto?
问:
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 的返回类型是 。auto
operator==
bool
注意:这是一个 wiki 风格的问答,其主要目标是提高对限制性语言设计和旨在解决它的 c++26 提案的认识。
答:
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 明确要求默认相等运算符必须具有声明的返回类型 ,而不是简单地指定其返回类型必须为 。我们认为上面的每个示例都有一个直观清晰的含义:占位符返回类型与默认正文实际返回的类型正确匹配。我们建议放宽目前的限制,并允许这些声明的格式正确。
bool
bool
从本质上讲,该提案将使推导的返回类型在预期特定返回类型的情况下有效。它不会更改有效返回类型的集。
实施挑战和边缘案例
值得注意的是,当涉及到有效返回类型集时,编译器存在一些分歧。例如:
// only clang rejects this, other compilers allow it
friend bool operator==(const C, const C) = default;
但是,这种分歧不应该妨碍提案,因为它提出了“规范”返回类型:
默认的二级比较运算符函数应具有返回类型。如果其声明的返回类型包含占位符类型,则其返回类型将推断为 from 。
bool
return true;
评论
0赞
Barry
11/14/2023
这种“边缘情况”与返回类型无关(该函数非常返回),而是与参数类型有关 - 因为参数需要两者或两者兼而有之(而不是两者)。我不确定为什么其他实现允许它,因为要么添加 s(以避免复制)要么删除 s(因为它们毫无意义?bool
C
C const&
C const
&
const
评论