Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of for_each on map elements

I have a map where I'd like to perform a call on every data type object member function. I yet know how to do this on any sequence but, is it possible to do it on an associative container?

The closest answer I could find was this: Boost.Bind to access std::map elements in std::for_each. But I cannot use boost in my project so, is there an STL alternative that I'm missing to boost::bind?

If not possible, I thought on creating a temporary sequence for pointers to the data objects and then, call for_each on it, something like this:

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)); 

It looks too obfuscated and I don't really like it. Any suggestions?

like image 824
Antonio Pérez Avatar asked May 17 '10 15:05

Antonio Pérez


People also ask

What is the use of MAP in CPP?

First, a map allows fast access to the value using the key. This property is useful when building any kind of index or reference. Second, the map ensures that a key is unique across the entire data structure, which is an excellent technique for avoiding duplication of data.


2 Answers

C++11 allows you to do:

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

C++17 allows you to do:

for (const auto& [key, value] : myMap) {     std::cout << key << " has value " << value << std::endl; } 

using structured binding.

UPDATE:

const auto is safer if you don't want to modify the map.

like image 153
Sebastian Avatar answered Sep 28 '22 02:09

Sebastian


You can iterate through a std::map object. Each iterator will point to a std::pair<const T,S> where T and S are the same types you specified on your map.

Here this would be:

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

If you still want to use std::for_each, pass a function that takes a std::pair<const int, MyClass>& as an argument instead.

Example:

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

And pass it to std::for_each:

std::for_each(Map.begin(), Map.end(), CallMyMethod); 
like image 29
ereOn Avatar answered Sep 28 '22 04:09

ereOn