Jump to content

  • Log In with Google      Sign In   
  • Create Account


How to use boost::unordered_map with for_each?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
13 replies to this topic

#1 blackfe2010   Members   -  Reputation: 150

Like
0Likes
Like

Posted 06 November 2012 - 03:14 AM

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.

Sponsor:

#2 Brother Bob   Moderators   -  Reputation: 7405

Like
1Likes
Like

Posted 06 November 2012 - 04:30 AM

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.

#3 Álvaro   Crossbones+   -  Reputation: 10625

Like
1Likes
Like

Posted 06 November 2012 - 04:40 AM

In C++11:
for (auto entry : g_map)
    entry.second->doSomething(p1, p2);


#4 blackfe2010   Members   -  Reputation: 150

Like
0Likes
Like

Posted 06 November 2012 - 07:35 AM

thanks, it's works well.

but what's means of [=] ?

#5 Brother Bob   Moderators   -  Reputation: 7405

Like
0Likes
Like

Posted 06 November 2012 - 07:54 AM

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.

#6 blackfe2010   Members   -  Reputation: 150

Like
0Likes
Like

Posted 06 November 2012 - 08:18 AM

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?

Edited by blackfe2010, 06 November 2012 - 08:18 AM.


#7 Brother Bob   Moderators   -  Reputation: 7405

Like
0Likes
Like

Posted 06 November 2012 - 10:06 AM

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.

#8 Bregma   Crossbones+   -  Reputation: 4358

Like
0Likes
Like

Posted 06 November 2012 - 10:52 AM

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"?

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?

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?

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.

Edited by Bregma, 06 November 2012 - 10:53 AM.

Stephen M. Webb
Professional Free Software Developer

#9 Yrjö P.   Crossbones+   -  Reputation: 1410

Like
0Likes
Like

Posted 06 November 2012 - 01:10 PM

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

Edited by Stroppy Katamari, 06 November 2012 - 01:14 PM.


#10 Yrjö P.   Crossbones+   -  Reputation: 1410

Like
0Likes
Like

Posted 06 November 2012 - 01:16 PM

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? :-(

#11 blackfe2010   Members   -  Reputation: 150

Like
0Likes
Like

Posted 07 November 2012 - 09:34 PM

Hi, I'm come back.

Sorry, I found i use vs2008 in one of my computer.
So I can't use c++11 like:

<br /> for (auto entry : g_map) entry.second->doSomething(p1, p2);<br />

and

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



And I want use boost::bind to solute this problem.

At first, I want to bind member variables std::pair<int,boost::shared_ptr<TEST>>::second
[source lang="cpp"]for_each( g_map.begin(), g_map.end(), boost::bind(&std::pair<int,boost::shared_ptr< TEST > >::second,_1));[/source]
But it's failed, why?

#12 blackfe2010   Members   -  Reputation: 150

Like
0Likes
Like

Posted 08 November 2012 - 04:09 AM

I'm find the problem.

I haven't wrt the default constructor...

#13 Yrjö P.   Crossbones+   -  Reputation: 1410

Like
0Likes
Like

Posted 08 November 2012 - 04:45 AM

Yeah, you can start from that and add an outer bind that binds to &TEST::doSomething.

Is there any reason you can't upgrade your Visual Studio to a new version and start using modern language features?

#14 Álvaro   Crossbones+   -  Reputation: 10625

Like
0Likes
Like

Posted 08 November 2012 - 09:34 AM

Why insist on using for_each? If the syntax is so cumbersome that you (or I) can't figure it out, why not use an old-fashioned loop?

for (boost::unordered_map<int,boost::shared_ptr<TEST> >::iterator it = g_map.begin(), end = g_map.end(); it != end; ++it)
  it->second->doSomething(p1, p2);





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS