【问题标题】:map Comparison Constructor Parameter地图比较构造函数参数
【发布时间】:2016-03-02 20:21:01
【问题描述】:

为什么我不能将比较函子作为构造函数参数传递给map:

map<int, string, greater<int>> foo;
//map<int, string> foo(greater<int>()); Doesn't work

或者为什么我不能在不提供自己的比较类型的情况下传递 lambda:

map<int, string, function<bool(const int&, const int&)>> bar([](const int& lhs, const int& rhs){ return lhs > rhs; });
//map<int, string> bar([](const int& lhs, const int& rhs){ return lhs > rhs; }); Doesn't work

我希望能够声明 map&lt;int, string&gt; 并使用比较器构造它。为什么我不能?

[Live Example]

【问题讨论】:

  • 因为这会涉及一些类型擦除,这不是最佳的?
  • @PiotrSkotnicki 你是说函子版本?但是map 不提供比较构造函数吗? cplusplus.com/reference/map/map/map 这不正是这个目的吗?
  • @JonathanMee 它用于初始化存储在地图中的实际比较器。在构造函数之外不知道其类型的情况下如何存储该比较器
  • @NathanOliver 你是说我们必须在map 模板中有类型,因为我们可以只使用一个指针?

标签: c++ templates dictionary comparator constructorargument


【解决方案1】:

这个问题源于一个误解。要清除它:

函子是对象不是函数

尝试将函数指针或 lambda 分配给对象没有任何意义。所以这是无法做到的:map&lt;int, string&gt; bar([](const int&amp; lhs, const int&amp; rhs){ return lhs &gt; rhs; }); 定义采用函数指针或 lambda 的 map 的方法是使用问题中的模板参数:map&lt;int, string, function&lt;bool(const int&amp;, const int&amp;)&gt;&gt;

问题中两个构思不当的选项之间存在另一个误解:map&lt;int, string, [](const int&amp; lhs, const int&amp; rhs){ return lhs &gt; rhs; }&gt; 不起作用,因为比较器模板参数是成员的 type map,不是初始化值。 因此,使用函数指针或 lambda 比较器的 map 必须始终将该值传递给 map 构造函数:map&lt;int, string, function&lt;bool(const int&amp;, const int&amp;)&gt;&gt; bar([](const int&amp; lhs, const int&amp; rhs){ return lhs &gt; rhs; }) 否则 function&lt;bool(const int&amp;, const int&amp;)&gt;() 将用于在 map 中进行比较。

现在这可能已经很清楚了,但是由于函子是对象,因此您不能传递不相关的对象是完全不同类型对象的构造值。调用 map&lt;int, string&gt; foo(greater&lt;int&gt;()) 就像调用 less&lt;int&gt; foo = greater&lt;int&gt;。 对于比较器模板参数是仿函数的map,唯一可接受的兼容器构造函数参数是可以在模板参数中转换为仿函数类型的对象的东西:map&lt;int, string, greater&lt;int&gt;&gt; foo(greater&lt;int&gt;{}) 这显然是不必要的, 因为如果没有提供参数并且默认构造了 greater&lt;int&gt; ,则将导致 map 的相同成员初始化,因此 map&lt;int, string, greater&lt;int&gt;&gt; 就足够了。

【讨论】:

  • map&lt;int, string, greater&lt;int&gt;&gt; foo(greater&lt;int&gt;()) 是一个函数声明(最麻烦的解析)
  • @PiotrSkotnicki 呃,谢谢。显然我没有尝试,因为它有点毫无意义。我已经编辑并实际测试了它现在可以工作:ideone.com/1Ygrze
猜你喜欢
  • 1970-01-01
  • 2018-07-19
  • 2020-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多