【问题标题】:Passing my compar function to std::multiset with C++11使用 C++11 将我的比较函数传递给 std::multiset
【发布时间】:2014-09-11 01:01:36
【问题描述】:

我有一个 std::multiset,它存储 std::pair。我希望第一个属性对唯一性没有限制,但我希望第二个属性是唯一的。所以,我决定将我自己的函数传递给 multiset,以实现这一点(如果没有,请告诉我)。

根据this 的回答,我写了一个类似的函数,但它失败了,我不知道为什么(不知道 λ - 我是希腊人:))。

auto f = [](std::pair<float, int>& a, std::pair<float, int>& b) {
  return (a.first < b.first && a.second != b.second);
};

错误:

error: expression ‘#‘lambda_expr’ not supported by dump_expr#<expression error>’ is not a constant-expression
sorry, unimplemented: non-static data member initializers
error: unable to deduce ‘auto’ from ‘<expression error>’

【问题讨论】:

  • 这意味着我走错了路@T.C.。我该怎么办?
  • 我不明白你的唯一性标准。您正在使用multiset,因此多个比较相等的键将存储在容器中。
  • 我认为主要问题是 lambda 需要采用 const &amp; 或按值
  • 您之前的评论似乎表明您认为 multiset 与多线程有关。容器根本不是线程安全的,除了const 成员函数,可以并发访问。 multi 仅表示容器将存储重复项,即比较相等的键。 set 只会存储唯一的密钥。
  • 如果不是希腊语,那就是野蛮人。

标签: c++ c++11 stl lambda multiset


【解决方案1】:

由于您使用的是multiset,而不是set,因此多个比较相等的键仍将存储在容器中,因此我不确定您在谈论唯一性时的意思。

假设您的意思是您只希望 pair 中的第二个元素影响排序,您可以使用如下 lambda:

auto f = [](std::pair<float, int> const& a, std::pair<float, int> const& b) {
  return a.second < b.second;
};
std::multiset<std::pair<float, int>, decltype(f)> m(f);

Live demo

【讨论】:

  • 谢谢,我会接受另一个答案,因为它首先出现并且公平竞争。 :)
  • @G.Samaras 您接受最佳答案,这里没有公平竞争的问题。我们不是在玩游戏。那些使用 SO 来获得声誉而不是知识的人是傻瓜。
  • 好点@40two。我仍然会保留另一个答案,因为那是第一个。 :)
  • MSVC 2013 还不允许这样做。
  • @AndyG 这是一个错误,我已经看到它报告了连接。即使您传入实例,MSVC 标准库也会尝试默认构造比较器。编辑:发现错误报告:connect.microsoft.com/VisualStudio/feedback/details/727957/… 显然已在 VS2015 中修复。
【解决方案2】:

我认为您不能将 lambda(运行时构造)作为模板参数(编译时构造)传递。使用带有 operator() 的结构来代替:

#include <set>
struct my_compare {
  bool operator() (const std::pair<float, int>& a, const std::pair<float, int>& b) {
    return (a.first < b.first && a.second != b.second);
  };
};
int main(int argc, char ** argv) {
  std::multiset<std::pair<float, int>, my_compare> set;
  return 0;
}

或者,使用 lambda 和 decltype(如 Praetorian 的回答):

#include <set>  
int main(int argc, char ** argv) {
  auto my_compare = [](const std::pair<float, int>& a, const std::pair<float, int>& b) {
    return (a.first < b.first && a.second != b.second);
  };
  std::multiset<std::pair<float, int>, decltype(my_compare)> set(my_compare);
  return 0;
}

【讨论】:

  • 在 GCC 4.9 上,我确实收到了与您看到的不同的错误:temp.cpp:13:40: error: template argument for template type parameter must be a type.
  • 我提供的链接中的人建议使用 λ。添加set.insert(std::make_pair(0.1, 1)); 看看会发生什么。 @T.C. 有评论。说 multiset 需要强排序,而我们的比较没有!
  • 显然 insert() 调用失败的原因是编译器对参数不是 const 感到不满。我会更新我的答案。
猜你喜欢
  • 2021-11-04
  • 2014-01-16
  • 2013-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多