Jump to content
  • Advertisement
Sign in to follow this  
thedevdan

Boost... wow

This topic is 5175 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Will someone explain how boost's for_each works? It apperently can take an expression, and exectute it:
for_each(a.begin(), a.end(), std::cout << _1 << ' ');
I downloaded the library, but it looks like I will have to read up on tons of boost's types. Does anyone have a short, simple explaination of how on earth an expression can be passed to a function? Or am I overestimating it?

Share this post


Link to post
Share on other sites
Advertisement
for_each is a STL algorithms that can be implemented as follow.

template<typename FwdIter, typename Functor>
Functor for_each( FwdIter begin, FwdIter end, Functor func)
{
while(begin != end)
func(*begin++);
return func;
}


The real magic thingy is that unassuming _1 placeholder.

_1 is a reference to a global object of type boost::lambda::placeholder1_type.

operator<<() is overloaded to take such an object as a parameter, returning a function object which, when called, do perform the appropriate action.

That is std::cout << _1 returns an object holding a reference to std::cout which, when called with a parameter foo does call operator<<(std::cout, foo).

That 'function call' operator is templated to accept any foo parameter.

Further work is done so that the function object returned can be used as _1 was originally, making further combination, like std::cout << _1 << ' ' possible.

There's a lot more going on behind the scenes - boost::lambda is one of the most complicated libraries in Boost.

Share this post


Link to post
Share on other sites
Quote:
Original post by Fruny
for_each is a STL algorithms that can be implemented as follow.

template<typename FwdIter, typename Functor>
Functor for_each( FwdIter begin, FwdIter end, Functor func)
{
while(begin != end)
func(*begin++);
return func;
}


The real magic thingy is that unassuming _1 placeholder.

_1 is a reference to a global object of type boost::lambda::placeholder1_type.

operator<<() is overloaded to take such an object as a parameter, returning a function object which, when called, do perform the appropriate action.

That is std::cout << _1 returns an object holding a reference to std::cout which, when called with a parameter foo does call operator<<(std::cout, foo).

That 'function call' operator is templated to accept any foo parameter.

Further work is done so that the function object returned can be used as _1 was originally, making further combination, like std::cout << _1 << ' ' possible.

There's a lot more going on behind the scenes - boost::lambda is one of the most complicated libraries in Boost.


Nice reply.

So they overload cout's << stream operator? How is that done without including their own iostream with boost?

Share this post


Link to post
Share on other sites
Quote:
So they overload cout's << stream operator?


If I understand fruny correctly they did not. They've created a templated << operator which takes two arguments (the two sides of the << operator) the first of which can be any type specified by the template parameter, the second of which is of type boost::lambda::placeholder1_type. This operator then returns an reference that when called using the ( ) operator calls operator << passing in as the first arugment what was on the left of the original << operator and on the right whatever was passed to the ( ) operator when it was called.

Share this post


Link to post
Share on other sites
Quote:
Original post by Monder
Quote:
So they overload cout's << stream operator?


If I understand fruny correctly they did not. They've created a templated << operator which takes two arguments (the two sides of the << operator) the first of which can be any type specified by the template parameter, the second of which is of type boost::lambda::placeholder1_type. This operator then returns an reference that when called using the ( ) operator calls operator << passing in as the first arugment what was on the left of the original << operator and on the right whatever was passed to the ( ) operator when it was called.


Nifty. That does make it seem a lot worse though. For example, x += 10 could not be used as the expression.

Share this post


Link to post
Share on other sites
Quote:
Original post by thedevdan
Nice reply.

So they overload cout's << stream operator? How is that done without including their own iostream with boost?


First, it is not "cout's << stream operator". operator<< is the bitshift operator, which just happen to also be overloaded for std::basic_ostream, of which std::cout is an instance, to do stream output.

But, yes, they do write an overload for basic_ostream (they treat it as a special case, see boost/lambda/detail/operators.hpp). They do refer to the standard iostream classes which are included with your compiler. They do pull some tricks so as not to require you to include the appropriate iostream headers before the boost::lambda headers -- template metaprogramming at its best -- but you still have to include them yourself at some point.

Share this post


Link to post
Share on other sites
Quote:
Original post by Fruny
Quote:
Original post by thedevdan
Nice reply.

So they overload cout's << stream operator? How is that done without including their own iostream with boost?


First, it is not "cout's << stream operator". operator<< is the bitshift operator, which just happen to also be overloaded for std::basic_ostream, of which std::cout is an instance, to do stream output.

But, yes, they do write an overload for basic_ostream (they treat it as a special case, see boost/lambda/detail/operators.hpp). They do refer to the standard iostream classes which are included with your compiler. They do pull some tricks so as not to require you to include the appropriate iostream headers before the boost::lambda headers -- template metaprogramming at its best -- but you still have to include them yourself at some point.


I know that << is the bitshift operator, I was being more descriptive. Still, it doesn't seem terribly useful as you can't have normal expressions like x += 10. Thanks for you persistent help!

Share this post


Link to post
Share on other sites
Quote:
Nifty. That does make it seem a lot worse though. For example, x += 10 could not be used as the expression.


It sure can, they also made overloads for operator +=.

  GNU nano 1.3.2                    File: foo.cc                      Modified

#include <iostream>
#include <boost/lambda/lambda.hpp>
#include <vector>
#include <algorithm>

using namespace std;
using namespace boost::lambda;

int main()
{
vector<int> vec;
vec.push_back(vec.size());
vec.push_back(vec.size());
vec.push_back(vec.size());
vec.push_back(vec.size());
vec.push_back(vec.size());

for_each( vec.begin(), vec.end(), _1 += 10);
for_each( vec.begin(), vec.end(), cout << _1 << '\n' );

int sum = 0;

for_each( vec.begin(), vec.end(), sum += _1 );
// though you're better off using accumulate()

cout << sum << endl;

}


There are limitations to what it can do though, you should read the doc for details.

Share this post


Link to post
Share on other sites
Quote:
Original post by Fruny
Quote:
Nifty. That does make it seem a lot worse though. For example, x += 10 could not be used as the expression.


It sure can, they also made overloads for operator +=.

*** Source Snippet Removed ***


Geeze, they must have worked hard. [wow]

So it works with any single expression using STL/built-in-types (or anything castable to them)?

Still, I definitely see what you mean about fighting the language. I still am confused what _1 evalutates to in 'sum += _1'. I guess it picks up it's value from a previous for_each.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!