Использование 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!
Другими словами, использование% в формате фактически заменяет строковые данные тем, что вы в них используете. Круче то, что второе использование выше молча провалится.
Я знаю, отчасти нелогично, но это то, что есть.