我需要手动声明">="和"<="运算符吗?

6
如果我已经定义了operator >operator <(以及operator ==),我是否需要定义operator >=operator <=,或者如果我有意不声明它们,编译器会为我自动声明它们吗?
另外,如果我定义了operator ==,编译器会为我声明operator !=吗?

2
如果你已经定义了operator<operator==,你可以引入std::rel_ops命名空间来提供其他的运算符,但这并不是一个真正的好的解决方案Boost.Operators才是正确的做法。 - Praetorian
使用继承来节省输入一些运算符的时间,总感觉不太对劲。我宁愿手动添加它们。=) - Jamin Grey
从提供功能的类派生还具有很好的文档价值。这是概念的原始形式。 - TemplateRex
3个回答

6
不,编译器不会自动声明/定义任何您没有手动定义的运算符。但是,Boost.Operators 可能会符合您的要求 - 它正好可以做到您希望编译器执行的操作。

当然,它们生成了不错的默认复制构造函数等。本来希望能有一个简单的自动生成的*operator!=(other) { return !(*this == other); }*。哦,好吧,感谢您的回答!我会等一会再接受它。 - Jamin Grey
1
+1 Boost.Operators 的维护者(Daniel Frey)有一个非官方的端口,称为 df.operators,将该库移植到了 C++11(rvalue 重载和 noexcept)。 - TemplateRex

5
编译器本身不会为你做任何事情,但通过继承适当的类,自动生成相对简单,例如:
template< typename DerivedType >
class ComparisonOperators
{
public:

    friend bool         operator!=( 
                            DerivedType const&  lhs,
                            DerivedType const&  rhs )
    {
        return !(lhs  == rhs);
    }

    friend bool         operator<=( 
                            DerivedType const&  lhs,
                            DerivedType const&  rhs )
    {
        return !(rhs < lhs);
    }

    friend bool         operator>( 
                            DerivedType const&  lhs,
                            DerivedType const&  rhs )
    {
        return rhs < lhs;
    }

    friend bool         operator>=( 
                            DerivedType const&  lhs,
                            DerivedType const&  rhs )
    {
        return !(lhs < rhs);
    }

protected:
                        ~ComparisonOperators() {}
} ;

在你的类中定义<==,并从此派生,你将获得所有运算符:
class MyClass : public ComparisonOperators<MyClass>
{
    //  ...
public:
    bool operator==( MyClass const& other ) const;
    bool operator<( MyClass const& other ) const;
    //  ...
};

请注意:我手动简化了我实际使用的版本,它定义了==<,查找成员函数compareisEqual,并在没有isEqual时使用compare进行==!=比较。我认为我没有引入任何错误,但是你永远不知道。


我倾向于使用int compare(DerivedType const &o),它返回负数、正数或0值(传统的C方法)。通常==<的代码非常相似,因此将它们合并在一起很好。 - edA-qa mort-ora-y
3
Boost.Operators不就是已经为你完成了这个功能吗?;-) - Arne Mertz
是的。那是上面的“compare”的签名。规则是:只有相等比较才能用“isEqual”(如果使用关系运算符,将无法编译);如果需要相等和关系比较,则使用“compare”;如果可以更快地执行相等比较,那么可以同时提供两者。而且,“ComparisonOperators”类中还有一些元编程技巧,可以调用正确的函数。 - James Kanze
对于我发布的版本是这样,但对于我实际使用的版本则不是。但我不知道Boost运算符的存在;我的实际类比Boost更早,并且做了更多的事情。(我的解决方案也适用于只有一个类:您不必区分“less_than_comparable”和“equality_comparable”。我不知道这是优势还是劣势。) - James Kanze

0

这里已经有一些使用boost和继承的好答案了。但正如某人所指出的 - 使用继承来创建运算符似乎是错误的。

我知道在C++中,#define是“禁忌”的,但在这里我仍然使用它。

我在我的通用实用程序包含文件中有一个#define,它像这样:

#define CREATE_COMPARITORS(name)                              \
inline bool operator>(const name &o){return o<*this;}         \
inline bool operator<=(const name &o){return not (o<*this);}  \
inline bool operator>=(const name &o){return not (*this<o);}  \
inline bool operator!=(const name &o){return not (*this==o);}

那么如果我有一个类,我只需要声明 operator<operator==

class ttt{
  //...
  bool operator<(const ttt &o);
  bool operator==(const ttt &o);
  CREATE_COMPARITORS(ttt);
  //...
};

你可能需要证明那个“似乎...不对”的说法。目前为止,我更相信Boost库的设计者,而不是你没有证据的观点。 - djechlin
在这个帖子中,我引用了另一个人的话,他说“使用继承来省略几个运算符,总觉得不太对劲”。现在,如果你想因为我的回答没有帮助或没有添加任何内容而给我投反对票,那没问题。但是,如果你只是因为我是许多不喜欢Boost及其处理方式的人之一,而你恰好是另一群喜欢Boost的人之一,就给我投反对票,那你就是滥用你的权力。 - rabensky
建议使用 #define 而非继承,但未说明继承的问题所在,也未解释这段代码为何不会出现通常宏定义所带来的问题。 - djechlin
Boost做了很多滥用语言的事情,来实现那些原本不存在的功能,作为后来被标准化的功能的试验田。Boost设计得非常好,但有时必须使用一些技巧来让代码工作,因为语言的限制。继承功能是否正确并不是一个大问题,但说“Boost这样做,所以它一定是一个好的实践”并不一定正确。我非常喜欢Boost!设计它的人非常聪明,比我更优秀的程序员。但这并不意味着它是一个好的实践。 - Jamin Grey
哦,另外,boost也使用宏。既然Boost使用它,它们一定很好!= P 故意挑逗@djechlin(只是为了轻松一下气氛,不是真的主张或抨击使用宏)。也没有故意抨击djechlin。=) - Jamin Grey
@JaminGrey,你提到Boost谨慎使用语言特性的观点很好,这是我没有考虑到的。否则,我的反对意见不变。 - djechlin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接