在地图元素上使用for_each

我有一个地图,我想在每个数据types对象成员函数上执行调用。 我还知道如何在任何序列上做到这一点,但有可能在关联容器上做到这一点?

我能find的最接近的答案是: Boost.Bind访问std :: for_each中的std :: map元素 。 但是我不能在我的项目中使用boost,所以,有没有一个STL的替代品,我错过了提高::绑定?

如果不可能的话,我想创build一个指向数据对象的临时序列,然后在它上面调用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)); 

它看起来太混乱,我不太喜欢它。 有什么build议么?

你可以遍历一个std::map对象。 每个迭代器都将指向一个std::pair<const T,S> ,其中TS是您在map上指定的相同types。

这里是:

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

如果你仍然想使用std::for_each ,请传递一个函数,它将std::pair<const int, MyClass>&replace为一个参数。

例:

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

并传递给std::for_each

 std::for_each(Map.begin(), Map.end(), CallMyMethod); 

C ++ 11允许你做:

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

更新:

如果你不想修改地图,const auto会更安全。

如何一个普通的C + +? (根据@Noah Roberts的说明修正的例子)

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

不幸的是,你没有Boost,但是如果你的STL实现有扩展,那么你可以编写mem_fun_ref和select2nd来创build一个适合for_each使用的函数。 代码看起来像这样:

 #include <algorithm> #include <map> #include <ext/functional> // GNU-specific extension for functor classes missing from standard STL using namespace __gnu_cxx; // for compose1 and select2nd class MyClass { public: void Method() const; }; std::map<int, MyClass> Map; int main(void) { std::for_each(Map.begin(), Map.end(), compose1(std::mem_fun_ref(&MyClass::Method), select2nd<std::map<int, MyClass>::value_type>())); } 

请注意,如果您无权访问compose1(或unary_compose模板)和select2nd,则它们相当容易编写。

C ++ 14带来了通用的lambdaexpression式。 这意味着我们可以很容易地使用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; }); 

我认为std :: for_each有时比基于循环的简单范围更适合。 例如,当你只想循环一个地图的子集。

对于那些偶然发现谷歌这个问题的程序员来说,有一个使用boost的好方法。

在这里解释: 是否有可能使用boost :: foreach与std :: map?

真正的例子,为您的方便:

 // typedef in include, given here for info : typedef std::map<std::string, std::string> Wt::WEnvironment::CookieMap Wt::WEnvironment::CookieMap cookie_map = environment.cookies(); BOOST_FOREACH( const Wt::WEnvironment::CookieMap::value_type &cookie, cookie_map ) { std::cout << "cookie : " << cookie.first << " = " << cookie.second << endl; } 

请享用。

它会为你工作吗?

 class MyClass; typedef std::pair<int,MyClass> MyPair; class MyClass { private: void foo() const{}; public: static void Method(MyPair const& p) { //...... p.second.foo(); }; }; // ... std::map<int, MyClass> Map; //..... std::for_each(Map.begin(), Map.end(), (&MyClass::Method)); 

只是一个例子:

 template <class key, class value> class insertIntoVec { public: insertIntoVec(std::vector<value>& vec_in):m_vec(vec_in) {} void operator () (const std::pair<key, value>& rhs) { m_vec.push_back(rhs.second); } private: std::vector<value>& m_vec; }; int main() { std::map<int, std::string> aMap; aMap[1] = "test1"; aMap[2] = "test2"; aMap[3] = "test3"; aMap[4] = "test4"; std::vector<std::string> aVec; aVec.reserve(aMap.size()); std::for_each(aMap.begin(), aMap.end(), insertIntoVec<int, std::string>(aVec) ); 

}

从我记忆中,C ++ map可以使用map.begin()返回键的迭代器,您可以使用该迭代器循环所有键直到到达map.end(),并获取相应的值: C ++ map

我写了一段时间回来做你正在寻找的东西。

 namespace STLHelpers { // // iterator helper type for iterating through the *values* of key/value collections // ///////////////////////////////////////////// template<typename _traits> struct _value_iterator { explicit _value_iterator(typename _traits::iterator_type _it) : it(_it) { } _value_iterator(const _value_iterator &_other) : it(_other.it) { } friend bool operator==(const _value_iterator &lhs, const _value_iterator &rhs) { return lhs.it == rhs.it; } friend bool operator!=(const _value_iterator &lhs, const _value_iterator &rhs) { return !(lhs == rhs); } _value_iterator &operator++() { ++it; return *this; } _value_iterator operator++(int) { _value_iterator t(*this); ++*this; return t; } typename _traits::value_type &operator->() { return **this; } typename _traits::value_type &operator*() { return it->second; } typename _traits::iterator_type it; }; template<typename _tyMap> struct _map_iterator_traits { typedef typename _tyMap::iterator iterator_type; typedef typename _tyMap::mapped_type value_type; }; template<typename _tyMap> struct _const_map_iterator_traits { typedef typename _tyMap::const_iterator iterator_type; typedef const typename _tyMap::mapped_type value_type; }; }