Использование boost::format в boost::lambda

По какой-то причине я не могу использовать boost::format в boost::lambda, Вот (надеюсь) скомпилируемое упрощение моего кода:

#include <algorithm>
#include <iomanip>
#include <iostream>

#include <boost/assign/list_of.hpp>
#include <boost/format.hpp>
#include <boost/lambda/lambda.hpp>

namespace bl = boost::lambda;

int main()
{
    const std::vector<int> v = boost::assign::list_of(1)(2)(3);
    std::for_each(v.begin(), v.end(), bl::var(std::cout) << std::setw(10) << bl::_1);
    std::for_each(v.begin(), v.end(), bl::var(std::cout) << boost::format("%10d") % bl::_1);
}
  • Первый std::for_each производит ожидаемый результат
  • Второй std::for_each выводит только пробелы без номера

Это почему? Я действительно не знаком с boost::lambda так что я могу упустить очевидное здесь.

Пожалуйста, не предлагайте std::copy основанные ответы: мой фактический код не работает на std::vector но на boost::fusion::vector (а также std::for_each на самом деле boost::fusion::for_each).

2 ответа

Решение

По какой-то причине ваш код оценивает boost::format("%10d") % bl::_1 немедленно, а не при каждом вызове лямбды.

Чтобы предотвратить это, вам нужно завернуть boost::format("%10d") в вызове bl::varтак же, как вы сделали с std::cout,

К сожалению, для этого требуется Boost.Lambda, чтобы определить тип возвращаемого значения для вызова operator%, что он не может сделать. Поэтому тип возвращаемого значения должен быть указан явно, используя bl::ret, Обратите внимание, что этот возвращаемый тип должен быть ссылкой, чтобы std::cout обращается к возвращенному объекту напрямую, а не к его копии.

Таким образом, мы получаем следующий код, который выдает ожидаемый результат:

std::for_each(v.begin(), v.end(), bl::var(std::cout) <<
    bl::ret<const boost::format &>(bl::var(boost::format("%10d")) % bl::_1));

Держу пари, что вы столкнулись с тем фактом, что используемый формат больше не используется.

boost::format f("...");

std::string s = f % ... ;
std::string s2 = f % other options...; // FAIL!  f has been changed by the above use!

Другими словами, использование% в формате фактически заменяет строковые данные тем, что вы в них используете. Круче то, что второе использование выше молча провалится.

Я знаю, отчасти нелогично, но это то, что есть.

Другие вопросы по тегам