[英]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 表达式具有某些优点:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.