gpt4 book ai didi

C++ 比较运算符重载常量与非常量行为

转载 作者:行者123 更新时间:2023-12-04 11:39:29 25 4
gpt4 key购买 nike

我最近注意到一些我自己无法弄清楚的运算符重载行为。以下两个类仅在 const 上有所不同关于 ClassA 的成员比较运算符重载.在 ClassB它们不是常量。一般来说,我知道人们总是更喜欢 const一,但我仍然对为什么我们会看到我将在下面描述的行为感兴趣。

#include <string>

class ClassA {
public:
explicit ClassA(double t) : _t(t) {}

std::string operator<=(int const& other) const {
return "A(<=)";
}

std::string operator==(int const& other) const {
return "A(==)";
}

friend std::string operator<=(int const& other, ClassA const& expr) {
return "A'(<=)";
}

friend std::string operator==(int const& other, ClassA const& expr) {
return "A'(==)";
}

private:
double _t;
};

class ClassB {
public:
explicit ClassB(double t) : _t(t) {}

std::string operator<=(int const& other) {
return "B(<=)";
}

std::string operator==(int const& other) {
return "B(==)";
}

friend std::string operator<=(int const& other, ClassB const& expr) {
return "B'(<=)";
}

friend std::string operator==(int const& other, ClassB const& expr) {
return "B'(==)";
}

private:
double _t;
};
现在我想在 const 中使用这些类和比较函数和非常量场景。
int
main(int argc,
char* argv[]) {
ClassA a1{0};
1==a1; //OK
1<=a1; //OK
ClassA const a2{0};
1==a2; //OK
1<=a2; //OK
ClassB b1{0};
1==b1; //NOT OK
1<=b1; //OK
ClassB const b2{0};
1==b2; //OK
1<=b2; //OK

return 0;
}
一切正常,但我标记的一行 NOT OK .这会引发编译器错误。
error C2446: '==': no conversion from 'ClassB' to 'int'
我的问题分为三个部分,但我希望有一个很好的理由可以回答所有问题。所以我希望将其发布到一个 SO 问题中仍然可以。

Why is the equality operator == not compiling, when the inequality <= is? Why does it matter for the friend functions whether the member functions are const or not? And why does making the ClassB object const fix it?


更新:
  • 在评论中@Eljay 指出该问题可能是由新的 C++20 特性造成的,该特性会自动生成带有反向参数的比较运算符。这显然使成员std::string operator==(int const& other) (重新安排后)更好的匹配1==b1 .经过一番挖掘,我发现规则说这些应该在 overload resolution 的规则中生成。 .

    1. rewritten candidates:
    • For the four relational operator expressions x<y, x<=y, x>y, and x>=y, all member, non-member, and built-in operator<=>'s found areadded to the set.
    • For the four relational operator expressions x<y, x<=y, x>y, and x>=y as well as the three-way comparison expression x<=>y, asynthesized candidate with the order of the two parameters reversed isadded for each member, non-member, and built-in operator<=>'s found.
    • For x!=y, all member, non-member, and built-in operator=='s found are added to the set.
    • For equality operator expressions x==y and x!=y, a synthesized candidate with the order of the two parameters reversed is added foreach member, non-member, and built-in operator=='s found.

    In all cases, rewritten candidates are not considered in the contextof the rewritten expression. For all other operators, the rewrittencandidate set is empty.


  • @463035818_is_not_a_number 指出了一些关于可以和不能编译不同版本代码的不同编译器的有趣发现。专供clanggcc带旗-std=c++2a最新版本 x86-64 clang 12.0.0x86-64 gcc 11.1不编译,而旧版本 x86-64 clang 9.0.1x86-64 gcc 9.4做。对于 VisualStudio,我们看到了类似的模式,带有标志 /std:c++latest .这里最新版本x64 msvc v19.28 (VS16.9)不编译,这里直接前辈x64 msvc v19.28做。这些测试是使用编译器资源管理器进行的 godbolt.org .
  • 特别有趣的是,clang 的编译器错误和 gcc提示问题是std::string operator==(int const& other)没有返回 bool .

  • 叮当
    error: return type 'std::string' (aka 'basic_string<char>') of selected 'operator==' function for rewritten '==' comparison is not 'bool'
    1==b1; //NOT OK
    gcc
    error: return type of 'std::string ClassB::operator==(const int&)' is not 'bool'
    1==b1; //NOT OK
    虽然这些都是非常有趣的见解,但最初的问题仍然悬而未决。

    最佳答案

    没有具体的答案。但是,让我们看看 documentation .
    对返回类型没有限制 对于重载运算符(因为返回类型不参与重载解析),但有规范的实现:

    ...the language puts no other constraintson what the overloaded operators do, or on the return type, but in general, overloadedoperators are expected to behave as similar as possible to thebuilt-in operators


    进而:

    ..the return types are limited by the expressions in which theoperator is expected to be used.

    For example, assignment operatorsreturn by reference to make it possible to write a = b = c = d,because the built-in operators allow that.


    我们挖 further :

    ...where built-in operators return bool, most user-defined overloads alsoreturn bool so that the user-defined operators can be used in the samemanner as the built-ins. However, in a user-defined operator overload,any type can be used as return type (including void).


    甚至 further (三路比较):

    If both operands have arithmetic types, or if one operand has unscopedenumeration type and the other has integral type, the usual arithmeticconversions are applied to the operands.


    所以,我会断言它 取决于实现 .在我的机器上它编译(g++)并运行:
    std::cout << (1==b1) << std::endl; // Prints B'(==)
    微小的重新更新
    @463035818_is_not_a_number :“这个问题是在 VS 中看到的。较新版本的 gcc 也拒绝这种用法,与 clang 相同。它看起来像是一个错误/缺失的功能,并在更新的版本中得到了修复。”
    这是 compiler explorer snippet与问题。

    关于C++ 比较运算符重载常量与非常量行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67938508/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com