C++ 运算符是否应==和<=&燃气轮机;在C++;20是作为成员还是作为自由函数实现?

C++ 运算符是否应==和<=&燃气轮机;在C++;20是作为成员还是作为自由函数实现?,c++,c++20,spaceship-operator,C++,C++20,Spaceship Operator,注:我认为这在技术上是重复的,但: C++20中对==的更改非常激进,我不确定 重提9年问题是正确的做法 我特别询问了被重写的运算符==和 编译器,而不是例如操作符,我从软件工程的角度认为,如果可能的话,人们总是更喜欢使用自由函数而不是成员方法。我相信所有的功能都是如此。为什么?它改进了封装,使函数不必“知道”类是如何实现的。当然,通常比较函数需要访问私有成员,然后使用friend或member函数就可以了(我还是更喜欢friend)。Scott Meyers用有效C++写了一点,第23项 我认

注:我认为这在技术上是重复的,但:

  • C++20中对
    ==
    的更改非常激进,我不确定 重提9年问题是正确的做法
  • 我特别询问了被重写的运算符
    ==

    编译器,而不是例如操作符
    ,我从软件工程的角度认为,如果可能的话,人们总是更喜欢使用自由函数而不是成员方法。我相信所有的功能都是如此。为什么?它改进了封装,使函数不必“知道”类是如何实现的。当然,通常比较函数需要访问私有成员,然后使用
    friend
    或member函数就可以了(我还是更喜欢
    friend
    )。Scott Meyers用有效C++写了一点,第23项


    我认为,在C++20中,比较应该是成员函数,除非您有非常令人信服的理由

    Lemme首先从C++17演算开始:我们通常以非成员的身份编写比较。原因是这是唯一允许进行双边比较的方法。如果我有一个想与
    int
    相比较的
    X
    类型,我不能让
    1==X{}
    与成员函数一起工作-它必须是一个自由函数:

    struct X { };
    bool operator==(X, int);
    bool operator==(int lhs, X rhs) { return rhs == lhs; }
    
    在这件事上没有太多选择。现在,将这些函数编写为纯自由函数是次优的,因为我们正在污染名称空间并增加查找中的候选函数数量-因此最好让它们成为隐藏的朋友:

    在C++20中,我们没有这个问题,因为比较本身是对称的。你可以写:

    struct X {
        bool operator==(int) const;
    };
    
    仅此声明就已经允许
    X{}==1
    1==X{}
    ,同时也没有为名称查找提供额外的候选项(只有当一方或另一方是
    X
    时,它才已经是候选项)

    此外,在C++20中,如果在类的声明中声明了比较,则可以使用默认比较。这些可以是成员函数或隐藏的朋友,但不是外部自由函数


    提供非成员比较的一个有趣的原因是我遇到了
    std::string
    。该类型的比较当前为非成员函数模板:

     template<class charT, class traits, class Allocator>
        constexpr bool
          operator==(const basic_string<charT, traits, Allocator>& lhs,
                     const basic_string<charT, traits, Allocator>& rhs) noexcept;
    
    模板
    康斯特普布尔酒店
    运算符==(常量基本字符串和lhs,
    const basic_string&rhs)无异常;
    
    这与将其作为成员(非模板)函数或隐藏朋友(非模板)函数有着重要的不同语义,因为它不允许作为模板进行隐式转换。因此,将此比较运算符转换为非模板将产生突然允许双方进行隐式转换的效果,这可能会破坏以前没有意识到这种可能性的代码


    但在任何情况下,如果您有一个类模板,并且希望避免在比较中进行转换,那么这可能是一个很好的理由,可以为您的比较运算符使用非成员函数模板。但仅此而已。

    这是基于观点的吗?好吧,这个选择会影响函数重载的解决。顺便说一句,如果你对C++23的改进有一个愿望列表,那么下面是我的贡献:如果一个类是一个简单的包装器(又称MyInt)那个只有一个T类型的成员,若语言允许我默认比较它,那个么可能会更好,比如我有一个Age(强类型结构),其中unsigned short是唯一的成员。然后布尔运算符==(uint16_t val)const==默认值;会是nice@NoSenseEtAl我想这需要新的关键字才能正常工作,并且不会破坏太多的向后兼容性。无论如何,由于元类可以添加到下一个标准中,所以您的愿望可能会得到满足;)
     template<class charT, class traits, class Allocator>
        constexpr bool
          operator==(const basic_string<charT, traits, Allocator>& lhs,
                     const basic_string<charT, traits, Allocator>& rhs) noexcept;