自定义类型作为地图的关键 - C ++

时间:2009-05-25 10:51:26

标签: c++ operator-overloading stdmap

我正在尝试将自定义类型指定为 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 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 之外,没有任何改变。我想知道为什么我的第一个代码无效?

有什么想法吗?

5 个答案:

答案 0 :(得分:32)

我怀疑你需要

bool operator<(const Foo& foo1) const;

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

只需要一个操作员的原因是它足以实现所需的排序。要回答抽象问题“必须先来b吗?”它足以知道a是否小于b。

答案 1 :(得分:3)

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

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

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

注意:我100%确定你需要 const ,因为我编译了这个例子。

答案 2 :(得分:0)

注意参数后面的const,这是使“你的”(比较中的左侧)对象不变。

请你详细说明一下吗?为什么如果你使成员const(据我所知,它意味着它不能改变对象的状态 - 例如修改私有变量)保证“你的”将是左侧?

答案 3 :(得分:0)

  

请你详细说明一下吗?为什么如果你使成员const(据我所知,它意味着它不能改变对象的状态 - 例如修改私有变量)保证“你的”将是左侧?

我还没有代表对此发表评论。

const并没有神奇地确保“你的”将是左手边。该海报说左手侧(即x

答案 4 :(得分:0)

其他答案已经解决了您的问题,但是我想提供一种替代解决方案。自C++11起,您可以使用lambda expression代替为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;
}

输出:

a:1
b:2

Code on Ideone