2

While trying to get comfortable with boost, stumbled into problem with using boost::function along with std::vector. I'm trying to do a simple thing: have a list of functions with similair signatures and then use all that functions with std::for_each on sample data. Here is the code:

typedef boost::function<int (const char*)> text_processor;
typedef std::vector<text_processor> text_processors;
text_processors processors;
processors.push_back(std::atoi);
processors.push_back(std::strlen);

const char data[] = "123";

std::for_each(processors.begin(), processors.end(),
    std::cout << boost::bind(&text_processors::value_type::operator(), _1, data) 
              << "\n"
);

So, with for_each I'm trying to write to standard output the result of applying every function to sample data. But it won't compile like this (some long message about missing operator << for bind result).

If I remove stream operators then I'll have compilable, but useless code. The trick is that I want to do function applying and text output in single for_each. What am I missing? Thought it should be easy with lambdas or smth like that, but can't figure out the correct solution.

elricbk
  • 107
  • 7

1 Answers1

4

The problem with your code is that you are trying to create a functor in place in a way that is not allowed (you cannot just throw code at the third argument of for_each, you need to pass a functor).

Without lambda support in the compiler you can use std::transform rather than std::for_each (not tested... but this should work):

std::transform( processors.begin(), processors.end(),
                std::ostream_iterator<int>( std::cout, "\n" ),
                bind( &text_processors::value_type::operator(), _1, data ) );

If your compiler supports lambdas you can do with it:

const char data[] = "123";
std::for_each(processors.begin(), processors.end(),
    [&data]( text_processors const & ) { 
        std::cout << boost::bind(&text_processors::value_type::operator(), _1, data) 
              << "\n"
    }
);

But then you can avoid the bind altogether:

std::for_each( processors.begin(), processors.end(),
               [&data]( text_processors::value_type & op ) {
                   std::cout << op( data ) << "\n";
               }
);
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • Thanks for reply. Solution with `std::transform` seems to pull the trick. I was trying to wrap my head around of couple of facts: `std::cout << boost::lambda::_1 << "\n"` is a functor and `boost::bind(...)` is a functor. But I still see no way to combine them in single functor to pass it to `std::for_each`. – elricbk Oct 03 '11 at 19:39
  • I have not used the boost lambda library, and it's been long since I read the docs, but IIRC there is a `boost::lambda::bind` that might be in the lines of what you need. Again, no real experience, your mileage might vary. – David Rodríguez - dribeas Oct 03 '11 at 19:57