How to use boost::unordered_map with for_each?

Started by
12 comments, last by alvaro 11 years, 5 months ago
Hi


class TEST
{
public:
TEST() {};
void doSomething(int a,int b);
};
boost::unordered_map<int,boost::shared_ptr<TEST>> g_map;
int main()
{
int p1=0;
int p2=1;
g_map[0]=boost::make_shared<TEST>();
g_map[1]=boost::make_shared<TEST>();
for_each(g_map.begin(),g_map.end(),how to write?);
returns 0;
}


Who can tell me how to write the for_each?
p1 and p2 are the parameters should send to TEST::doSomething.
Advertisement
The function is called with an std::pair<Tk, Tv> object, where Tk is the key type and Tv is the value type. For example, using a lambda expression:

for_each(
g_map.begin(),
g_map.end()
[](std::pair<int, std::shared_ptr<TEST>> const &foo){ /* key in foo.first and value in foo.second */ }
);

To call the member function doSomething on the TEST object, and passing p1 and p2 to it, you can implement the function to call doSomething on the value and capture the parameters p1 and p2 with the lambda expression.

for_each(
g_map.begin(),
g_map.end()
[=](std::pair<int, std::shared_ptr<TEST>> const &foo){ foo.second->doSomething(p1, p2); }
);

Replace std:: with boost:: at suitable places. I don't have boost installed on this machine so can only verify it with the std equivalents.
In C++11:
for (auto entry : g_map)
entry.second->doSomething(p1, p2);
thanks, it's works well.

but what's means of [=] ?
It is the capture part of the lambda expression syntax. I'm not sure if your question is about lambda expressions in general or if you are aware of them and just want to know why I use the equal sign in the capture part.

If you want to know about lambda expressions in general, then your best option is to just use your favorite search engine so you can read some proper written material instead of a quick forum post. But if you're just wondering about the capture part, then it simply means that the values are captured by value instead of being captured by reference (which would be [&]). The difference between a value and a reference capture is whether the variable inside the lambda expression is a copy of, or a reference to, the original variable. By value-capture is the default so it could actually have been left out.
ok, i think i need to learn some lambda expression.

but Is this the only solution to use "lumbda"?

And what the performance about the lumbda?

Can i use huge amount of lumbda expressions in my code?
alvaro's solution is better than a for_each call. But there are other options to lambda expressions to use with for_each if you really want to use it, such as a function object.

struct myfuncobj {
myfuncobj(int p1, int p2) : p1(p1), p2(p2) { }

void operator()(std::pair<int, std::shared_ptr<TEST>> const &foo) {
foo.second->doSomething(p1, p2);
}

private:
int p1, p2;
};
...
for_each(g_map.begin(), g_map.end() myfuncobj(p1, p2));

The function object is more or less equivalent to what the compiler would generate for the lambda expression, but has the drawback of being more code to write and that you have to separate the for_each-statement and its actual code.

ok, i think i need to learn some lambda expression.

Yes, assuming you have a compiler that supports the current C++ standard.

but Is this the only solution to use "lumbda"?
[/quote]
No. You can hand-craft a functor class (if your compiler does not support lambdas) or use std::bind (or boost::bind if your compiler does not support the current C++ standard).

And what the performance about the lumbda?
[/quote]
Generally as good as you can get. The compiler will effectively transform the expression into an inline function.

Can i use huge amount of lumbda expressions in my code?
[/quote]
Yes you can. Don't. You can use them frequently, but if the expression is more than a few (1 to 7, say) lines then from a readability standpoint you would benefit from writing a separate function and using std::bind if currying arguments is required. Short lambda expressions increase code readability, longer ones decrease it.

Stephen M. Webb
Professional Free Software Developer


Yes you can. Don't. You can use them frequently, but if the expression is more than a few (1 to 7, say) lines then from a readability standpoint you would benefit from writing a separate function and using std::bind if currying arguments is required. Short lambda expressions increase code readability, longer ones decrease it.
Long lambdas do not decrease code readability. The difference between this:
for (auto it=begin(container); it!=end(container); ++it)
{
... 20 lines ...
}
and this:for_each(begin(container),end(container),[](element &x)
{
... 20 lines ...
});
is just a matter of taste. I tend to like the for_each version when I can't use range-for.
You can use lambdas of whatever length when the functionality within is a one-off and not needed anywhere else in the code.
If the code is needed several times but only locally, you can still use a lambda and avoid polluting the outer scope with useless stuff:void someFunc()
{
auto snarf = [](foo &amp;amp;f) { /* snarfing a foo */ };
for_each(begin(manyFoos), end(manyFoos), snarf);
snarf(*begin(manyFoos)); // first foo needs to be snarfed twice
snarf(anotherFoo);
}
The forum editor seems to be bugged. If I try to edit the typos out, it just spawns more typos. Maybe it doesn't like the lambda syntax? :-(

This topic is closed to new replies.

Advertisement