如何使用自定义类型作为 C++ 中地图的键?

发布于 2024-07-21 05:21:40 字数 1086 浏览 12 评论 0原文

我正在尝试将自定义类型分配为 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之外,没有任何改变。 为什么我的第一个代码不起作用?

I am trying to assign a custom type as a key for std::map. Here is the type which I am using as key:

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;
};

When used with std::map, I am getting the following error:

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

If I change the struct to the one below, everything works:

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;
};

Nothing changed, except that the operator is overloaded as friend. Why does my first code not work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

终止放荡 2024-07-28 05:21:40

我怀疑您需要

bool operator<(const Foo& foo1) const;

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

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

I suspect you need

bool operator<(const Foo& foo1) const;

Note the const after the arguments, this is to make "your" (the left-hand side in the comparison) object constant.

The reason only a single operator is needed is that it is enough to implement the required ordering. To answer the abstract question "does a have to come before b?" it is enough to know whether a is less than b.

今天小雨转甜 2024-07-28 05:21:40

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

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

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

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

It's probably looking for const member operators (whatever the correct name is).
This works (note const):

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

EDIT: deleted operator> from my answer as it was not needed (copy/paste from question) but it was attracting comments :)

Note: I'm 100% sure that you need that const because I compiled the example.

涫野音 2024-07-28 05:21:40

其他答案已经解决了您的问题,但我想提供替代解决方案。 从 C++11 开始,您可以使用 lambda 表达式 而不是为您的 structoperator< >。 (您的映射不需要 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
b:2

Ideone 上的代码

The other answers already solve your problem, but I'd like to offer an alternative solution. Since C++11 you can use a lambda expression instead of defining operator< for your struct. (operator> is not needed for your map to work.) Providing a lambda expression to the constructor of a map has certain advantages:

  • I find the declaration of a lambda expressions to be simpler and less error-prone than that of operators.
  • This approach is especially useful if you can't modify the struct that you want to store in your map.
  • You can provide different comparison functions for different maps that use your struct as key.
  • You can still define operator< differently and use it for a different purpose.

As a result, you can keep your struct as short as follows:

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

And your map can then be defined in the following way:

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;
}

Output:

a: 1
b: 2

Code on Ideone

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文