在boost :: lambda中使用boost :: format

时间:2010-12-07 21:53:31

标签: c++ boost-lambda boost-format

出于某种原因,我未能在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 个答案:

答案 0 :(得分:4)

出于某种原因,您的代码会立即评估boost::format("%10d") % bl::_1,而不是每次调用lambda。

为防止这种情况发生,您需要将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));

答案 1 :(得分:2)

我敢打赌,您遇到的问题是所使用的格式不再可用。

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

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

换句话说,在格式上使用%实际上会将字符串数据替换为您对其进行的任何操作。更酷的是,上面的第二次使用将静默失败。

我知道,有点违反直觉,但事实就是如此。