在地图元素上使用for_each

Ant*_*rez 41 c++ algorithm stl stdmap std-pair

我有一个地图,我想在每个数据类型对象成员函数上执行调用.我还知道如何在任何序列上执行此操作但是,是否可以在关联容器上执行此操作?

我能找到的最接近的答案是:Boost.Bind访问std :: for_each中的std :: map元素.但是我不能在我的项目中使用boost,那么是否有一个STL替代品,我缺少boost :: bind?

如果不可能,我想创建一个指向数据对象的指针的临时序列,然后在其上调用for_each,如下所示:

class MyClass
{
public:
 void Method() const;
}

std::map<int, MyClass> Map;
//...

std::vector<MyClass*> Vector;
std::transform(Map.begin(), Map.end(), std::back_inserter(Vector), std::mem_fun_ref(&std::map<int, MyClass>::value_type::second));
std::for_each(Vector.begin(), Vector.end(), std::mem_fun(&MyClass::Method));
Run Code Online (Sandbox Code Playgroud)

它看起来太混淆了,我真的不喜欢它.有什么建议?

Seb*_*ian 85

C++ 11允许您:

for (const auto& kv : myMap) {
    std::cout << kv.first << " has value " << kv.second << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

更新:

如果您不想修改地图,则const auto更安全.


ere*_*eOn 53

您可以遍历std::map对象.每个迭代器都将指向您在std::pair<const T,S>其中指定的位置TS类型map.

这将是:

for (std::map<int, MyClass>::iterator it = Map.begin(); it != Map.end(); ++it)
{
  it->second.Method();
}
Run Code Online (Sandbox Code Playgroud)

如果您仍想使用std::for_each,请传递一个std::pair<const int, MyClass>&以参数为参数的函数.

例:

void CallMyMethod(std::pair<const int, MyClass>& pair) // could be a class static method as well
{
  pair.second.Method();
}
Run Code Online (Sandbox Code Playgroud)

并传递给std::for_each:

std::for_each(Map.begin(), Map.end(), CallMyMethod);
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的回答,但我想避免创建自己的循环。 (2认同)
  • @Antonio:这有什么特别的原因吗?任何基于模板的解决方案都应该生成一个代码,该代码最多只能****或更差.但不太可能更快.我编辑了我的答案,添加了一个更短的(但等效的解决方案). (2认同)

Chr*_*app 9

C++ 14带来了通用的lambdas.这意味着我们可以非常轻松地使用std :: for_each:

std::map<int, int> myMap{{1, 2}, {3, 4}, {5, 6}, {7, 8}};

std::for_each(myMap.begin(), myMap.end(), [](const auto &myMapPair) {
    std::cout << "first " << myMapPair.first << " second "
              << myMapPair.second << std::endl;
});
Run Code Online (Sandbox Code Playgroud)

我认为std :: for_each有时比基于循环的简单范围更适合.例如,当您只想循环遍历地图的子集时.


bob*_*bah 8

简单的C++怎么样?(示例根据@Noah Roberts的说明修复)

for(std::map<int, MyClass>::iterator itr = Map.begin(), itr_end = Map.end(); itr != itr_end; ++itr) {
  itr->second.Method();
}
Run Code Online (Sandbox Code Playgroud)

  • 过早的泛化是另一种邪恶的根源. (8认同)
  • ...可能是微不足道的.)那就是说,我不喜欢`for_each`.它大部分时间都很笨拙,而且表现力不强.理想情况下,我更喜欢C++ 0x中新的基于范围的for循环:`for(const map_pair&p:the_map){the_vec.push_back(p.second); }和`for(vec_element v&:the_vec){v.method(); }`.更简单易读,更简洁.接下来将伪造这样的功能,例如对于每个宏使用Boost.如果不是这样,lambda可以通过本地化算法来帮助我,但我认为`for_each`是一种不得已的事情. (4认同)
  • 可以说,除非您使用分析工具识别出瓶颈,否则下一个程序员更难理解和维护代码比优化代码更有价值. (3认同)