Использование std::vector‹boost::function› с boost::bind

Пытаясь освоиться с boost, столкнулся с проблемой использования boost::function вместе с std::vector. Я пытаюсь сделать простую вещь: получить список функций с похожими сигнатурами, а затем использовать все эти функции с std::for_each для выборочных данных. Вот код:

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

Итак, с помощью for_each я пытаюсь вывести на стандартный вывод результат применения каждой функции к выборочным данным. Но так не скомпилируется (какое-то длинное сообщение об отсутствии оператора << для результата bind).

Если я уберу потоковые операторы, у меня будет компилируемый, но бесполезный код. Хитрость в том, что я хочу выполнять применение функций и вывод текста в одном for_each. Что мне не хватает? Думал, что это должно быть легко с лямбда-выражениями или чем-то подобным, но не могу найти правильное решение.


person elricbk    schedule 02.10.2011    source источник


Ответы (1)


Проблема с вашим кодом заключается в том, что вы пытаетесь создать функтор на месте недопустимым способом (вы не можете просто добавить код в третий аргумент for_each, вам нужно передать функтор) .

Без поддержки лямбда в компиляторе вы можете использовать std::transform, а не std::for_each (не проверено... но это должно работать):

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

Если ваш компилятор поддерживает лямбды, вы можете сделать с ним:

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

Но тогда вы можете вообще избежать bind:

std::for_each( processors.begin(), processors.end(),
               [&data]( text_processors::value_type & op ) {
                   std::cout << op( data ) << "\n";
               }
);
person David Rodríguez - dribeas    schedule 02.10.2011
comment
Спасибо за ответ. Решение с std::transform похоже на трюк. Я пытался уложить в голове пару фактов: std::cout << boost::lambda::_1 << "\n" — это функтор, а boost::bind(...) — это функтор. Но я все еще не вижу возможности объединить их в один функтор, чтобы передать его std::for_each. - person elricbk; 03.10.2011
comment
Я не использовал лямбда-библиотеку boost, и я давно не читал документы, но во IIRC есть boost::lambda::bind, который может быть в строках того, что вам нужно. Опять же, нет реального опыта, ваш пробег может отличаться. - person David Rodríguez - dribeas; 03.10.2011