【问题标题】:boost::function & boost::lambda againboost::function & boost::lambda 再次
【发布时间】:2011-02-28 05:33:20
【问题描述】:

后续发帖:Using * Width & Precision Specifiers With boost::format

我正在尝试使用 boost::function 创建一个函数,该函数使用 lambda 来格式化带有 boost::format 的字符串。最终,我想要实现的是对具有格式的字符串使用宽度和精度说明符。 boost::format 不支持使用 * 宽度和精度说明符,如 in the docs 所示:

宽度或精度设置为星号 (*) printf 使用它来读取该字段 从一个论点。例如 printf("%1$d:%2$.*3$d:%4$.*3$d\n", 小时,分钟,精度,秒);这节课 不支持这种机制 现在。所以这样的精度或宽度字段 被解析悄悄地忽略了。

所以我正在尝试寻找其他方法来实现相同的目标。

这是我目前所拥有的,但不起作用:

#include <string>
#include <boost\function.hpp>
#include <boost\lambda\lambda.hpp>
#include <iostream>
#include <boost\format.hpp>
#include <iomanip>
#include <boost\bind.hpp>

int main()
{
 using namespace boost::lambda;
 using namespace std;

 boost::function<std::string(int, std::string)> f =
  (boost::format("%s") % boost::io::group(setw(_1*2), setprecision(_2*2), _3)).str();

 std::string s = (boost::format("%s") % f(15, "Hello")).str();

    return 0;
}

这会产生许多编译器错误:

1>------ Build started: Project: hacks, Configuration: Debug x64 ------
1>Compiling...
1>main.cpp
1>.\main.cpp(15) : error C2872: '_1' : ambiguous symbol
1>        could be 'D:\Program Files (x86)\boost\boost_1_42\boost/lambda/core.hpp(69) : boost::lambda::placeholder1_type &boost::lambda::`anonymous-namespace'::_1'
1>        or       'D:\Program Files (x86)\boost\boost_1_42\boost/bind/placeholders.hpp(43) : boost::arg<I> `anonymous-namespace'::_1'
1>        with
1>        [
1>            I=1
1>        ]
1>.\main.cpp(15) : error C2664: 'std::setw' : cannot convert parameter 1 from 'boost::lambda::placeholder1_type' to 'std::streamsize'
1>        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>.\main.cpp(15) : error C2872: '_2' : ambiguous symbol
1>        could be 'D:\Program Files (x86)\boost\boost_1_42\boost/lambda/core.hpp(70) : boost::lambda::placeholder2_type &boost::lambda::`anonymous-namespace'::_2'
1>        or       'D:\Program Files (x86)\boost\boost_1_42\boost/bind/placeholders.hpp(44) : boost::arg<I> `anonymous-namespace'::_2'
1>        with
1>        [
1>            I=2
1>        ]
1>.\main.cpp(15) : error C2664: 'std::setprecision' : cannot convert parameter 1 from 'boost::lambda::placeholder2_type' to 'std::streamsize'
1>        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>.\main.cpp(15) : error C2872: '_3' : ambiguous symbol
1>        could be 'D:\Program Files (x86)\boost\boost_1_42\boost/lambda/core.hpp(71) : boost::lambda::placeholder3_type &boost::lambda::`anonymous-namespace'::_3'
1>        or       'D:\Program Files (x86)\boost\boost_1_42\boost/bind/placeholders.hpp(45) : boost::arg<I> `anonymous-namespace'::_3'
1>        with
1>        [
1>            I=3
1>        ]
1>.\main.cpp(15) : error C2660: 'boost::io::group' : function does not take 3 arguments
1>.\main.cpp(15) : error C2228: left of '.str' must have class/struct/union
1>Build log was saved at "file://c:\Users\john\Documents\Visual Studio 2005\Projects\hacks\x64\Debug\BuildLog.htm"
1>hacks - 7 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

我可能缺乏对 boost 的 lambda 和函数的基本了解。我怎样才能让它工作?

【问题讨论】:

    标签: c++ boost


    【解决方案1】:

    我认为,对于这种情况,您应该使用 boost.bind 而不是 boost.lambda。部分问题在于 boost::io::group 是一个函数模板,它接受并返回可变数量的对象,因此很难为 function 声明创建适当的签名。我将创建一个带有简单签名的字符串格式化函数,然后使用 boost.bind 从中创建一个特定的格式化函数。即

    #include <string>
    #include <iomanip>
    #include <boost/function.hpp>
    #include <boost/format.hpp>
    #include <boost/bind.hpp>
    
    using namespace boost;
    using namespace std;
    
    string fmt_str(const string& s, int w, int p)
    {
        return (format("%s") % io::group(setw(w), setprecision(p), s)).str();
    }
    
    int main()
    {
        function<string (int, string)> f = bind(fmt_str, _2, _1, _1);
        string s = f(15, "Hello");
        return 0;
    }
    

    【讨论】:

      【解决方案2】:

      您应该再次查看 Boost.Lambda 的文档,看看它能做什么,不能做什么。例如,由于点运算符不可重载,因此您不能在这样的 lambda 表达式上调用像 str() 这样的成员函数。您需要为此使用bind

      bind(&format::str, … )
      

      据我所知,这实际上扩展到所有非运算符函数调用。至于创建格式对象,您需要通过以下方式推迟创建它:

      constructor<boost::format>(constant("%s"))  // untested
      

      您会看到,由于所有额外的噪音(绑定、构造函数、常量),您会得到一个相当复杂、冗长且难以破译的 lambda 表达式。最好的办法可能是完全避免它,只使用一个简单的函数对象

      struct myfunctor {
          string operator()(int a, string b) const {
              return …
          }
      };
      …
      void foo() {
          …
          boost::function<string(int, string)> f = myfunctor();
          …
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-11
        • 1970-01-01
        • 2016-03-16
        • 1970-01-01
        • 2011-06-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多