【问题标题】:Implementing operator< in C++在 C++ 中实现 operator<
【发布时间】:2011-03-01 16:31:54
【问题描述】:

我有一个包含几个数字字段的类,例如:

class Class1 {
    int a;
    int b;
    int c;
public:
    // constructor and so on...
    bool operator<(const Class1& other) const;
};

我需要使用此类的对象作为std::map 中的键。因此我实现了operator&lt;。在这里使用operator&lt; 的最简单实现是什么?

编辑: 可以假设&lt;的含义,只要其中任何一个字段不相等,就可以保证唯一性。

编辑 2:

一个简单的实现:

bool Class1::operator<(const Class1& other) const {
    if(a < other.a) return true;
    if(a > other.a) return false;

    if(b < other.b) return true;
    if(b > other.b) return false;

    if(c < other.c) return true;
    if(c > other.c) return false;

    return false;
}

这篇文章背后的全部原因是我发现上面的实现太冗长了。应该有更简单的东西。

【问题讨论】:

  • 您必须首先确定'

标签: c++ operators operator-overloading operator-keyword


【解决方案1】:

我假设你想实现字典顺序。

C++11 之前:

#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
bool Class1::operator<(const Class1& other) const
{
    return boost::tie(a, b, c) < boost::tie(other.a, other.b, other.c);
}

C++11 起:

#include <tuple>
bool Class1::operator<(const Class1& other) const
{
    return std::tie(a, b, c) < std::tie(other.a, other.b, other.c);
}

【讨论】:

  • 不错!但是对于我的特殊情况来说,提升太重了。
  • 太好了,从来没想过使用元组!
  • @Agnel Kurian:没有必要比这条领带更“使用”它。它也只有头文件,为了最大限度地减少构建影响(时间/依赖性),您可以将其隔离到一个单独的编译单元中(但对于发布版本,请考虑在头文件中进行内联!)
  • 使用最近的编译器,您可以在包含 标头后使用 std::tie :)
【解决方案2】:

我认为对map 的要求存在误解。

map 不需要你的类定义operator&lt;。它需要传递一个合适的比较谓词,默认为std::less&lt;Key&gt;,它在Key 上使用operator&lt;。

您不应该实现operator&lt; 以使您的密钥适合map。只有在为此类定义它时才应该实现它:即,如果它是有意义的。

你可以完美地定义一个谓词:

struct Compare: std::binary_function<Key,Key,bool>
{
  bool operator()(const Key& lhs, const Key& rhs) const { ... }
};

然后:

typedef std::map<Key,Value,Compare> my_map_t;

【讨论】:

    【解决方案3】:

    这取决于订购是否对您很重要。如果没有,你可以这样做:

    bool operator<(const Class1& other) const
    {
        if(a == other.a)
        {
             if(b == other.b)
             {
                 return c < other.c;
             }
             else
             {
                 return b < other.b;
             }
        }
        else
        {
            return a < other.a;
        }
    }
    

    【讨论】:

    • 谢谢!!这就是我一直在寻找的。​​span>
    • 或者,为了好玩,return a!=other.a?a&lt;other.a:b!=other.b?b&lt;other.b:c&lt;other.c;
    • 我看不出这比 OP 给出的“简单实现”更好。这个版本的可读性较差。
    【解决方案4】:

    避免多次缩进的版本是

    bool operator<(const Class1& other) const
    {
        if(a != other.a)
        {
            return a < other.a;
        }
    
        if(b != other.b)
        {
            return b < other.b;
        }
    
        return c < other.c;
    }
    

    作者的“Edit 2”版本平均比这个解决方案有更多的比较。 (最坏情况6到最坏情况3)

    【讨论】:

      【解决方案5】:

      你可以这样做:

      return memcmp (this, &other, sizeof *this) < 0;
      

      但这有很多警告 - 例如没有 vtbl,我敢肯定还有更多。

      【讨论】:

      • @Peter:OP 只想要to guarantee uniqueness as long as any of the fields are unequal,因此,添加一个 offsetof 来获取第一个关键字段的地址并确保关键字段是连续的,memcmp 应该可以解决问题。
      猜你喜欢
      • 2011-06-07
      • 2012-10-14
      • 1970-01-01
      • 2018-08-14
      • 1970-01-01
      • 2021-11-12
      • 1970-01-01
      • 1970-01-01
      • 2017-11-07
      相关资源
      最近更新 更多