繁体   English   中英

如何在 C++ 中使用自定义类型作为映射的键?

[英]How can I use a custom type as key for a map in C++?

我正在尝试将自定义类型分配为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 ,则一切正常:

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

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

我怀疑你需要

bool operator<(const Foo& foo1) const;

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

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

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

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

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

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

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

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

const并没有神奇地确保“你的”将是左手边。 海报说左手边(即x <y中的x)是调用比较的对象。 正如您使用运算符<的参数上的const保护y的成员免受更改一样,您还希望保护x的成员不受方法签名末尾的const的更改。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM