# Boost... wow

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

## 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 on other sites
either for_each is a macro or << is an overloaded operator either returning a reference or a value.

##### Share on other sites
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 on other sites
Quote:
 Original post by Frunyfor_each is a STL algorithms that can be implemented as follow.templateFunctor 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.

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

##### 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 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 on other sites
Quote:
 Original post by thedevdanNice 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 on other sites
Quote:
Original post by Fruny
Quote:
 Original post by thedevdanNice 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 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.

  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 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.

*** 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.

1. 1
Rutin
19
2. 2
3. 3
JoeJ
16
4. 4
5. 5

• 26
• 20
• 13
• 13
• 17
• ### Forum Statistics

• Total Topics
631700
• Total Posts
3001783
×