23

我正在尝试将自定义类型分配为std::map. 这是我用作键的类型:

struct Foo
{
    Foo(std::string s) : foo_value(s){}

    bool operator<(const Foo& foo1) {   return foo_value < foo1.foo_value;  }

    bool operator>(const Foo& foo1) {   return foo_value > foo1.foo_value;  }
    
    std::string foo_value;
};

与 一起使用时std::map,我收到以下错误:

error C2678: binary '<' : no operator found which takes a left-hand operand of type 'const Foo' (or there is no acceptable conversion) c:\program files\microsoft visual studio 8\vc\include\functional 143

如果我将其更改为struct以下,一切正常:

struct Foo
{
    Foo(std::string s) : foo_value(s)   {}

    friend bool operator<(const Foo& foo,const Foo& foo1) { return foo.foo_value < foo1.foo_value;  }

    friend bool operator>(const Foo& foo,const Foo& foo1) { return foo.foo_value > foo1.foo_value;  }
    
    std::string foo_value;
};

没有任何改变,除了操作符被重载为friend。为什么我的第一个代码不起作用?

4

3 回答 3

32

我怀疑你需要

bool operator<(const Foo& foo1) const;

请注意const参数之后,这是为了使“您的”(比较中的左侧)对象保持不变。

只需要一个运算符的原因是它足以实现所需的排序。要回答抽象问题“a 必须在 b 之前吗?” 知道 a 是否小于 b 就足够了。

于 2009-05-25T10:53:28.717 回答
3

它可能正在寻找 const 成员运算符(无论正确的名称是什么)。这有效(注意 const):

bool operator<(const Foo& foo1) const { return foo_value < foo1.foo_value;}

编辑:从我的答案中删除operator>,因为它不需要(从问题复制/粘贴),但它吸引了评论:)

注意:我 100% 确定您需要该const,因为我编译了该示例。

于 2009-05-25T11:03:41.707 回答
0

其他答案已经解决了您的问题,但我想提供一个替代解决方案。从C++11开始,您可以使用lambda 表达式而不是operator<为您的struct. (operator>您的地图不需要工作。)向地图的构造函数提供 lambda 表达式具有一定的优势:

  • 我发现 lambda 表达式的声明比运算符更简单且不易出错。
  • 如果您无法修改struct要存储在地图中的内容,此方法特别有用。
  • struct您可以为使用您作为键的不同地图提供不同的比较功能。
  • 您仍然可以operator<进行不同的定义并将其用于不同的目的。

因此,您可以保持struct如下简短:

struct Foo {
    Foo(std::string s) : foo_value(s) {}
    std::string foo_value;
};

然后可以通过以下方式定义您的地图:

int main() {
    auto comp = [](const Foo& f1, const Foo& f2) { return f1.foo_value < f2.foo_value; };
    std::map<Foo, int, decltype(comp)> m({ {Foo("b"), 2}, {Foo("a"), 1} }, comp);
    // Note: To create an empty map, use the next line instead of the previous one.
    // std::map<Foo, int, decltype(comp)> m(comp); 

    for (auto const &kv : m)
        std::cout << kv.first.foo_value << ": " << kv.second << std::endl;

    return 0;
}

输出:

甲:1
乙:2

Ideone 上的代码

于 2020-08-03T13:46:13.797 回答