2010-06-05 26 views
0

后续岗位:Using * Width & Precision Specifiers With boost::format的boost ::功能和提高::拉姆达再次

我试图用boost::function创建使用lambda表达式与boost::format格式化字符串的函数。最终,我试图实现的是使用宽度&精度说明符的格式的字符串。 boost::format不支持使用*宽度&精度说明的,如所指示in the docs

宽度或精度设置为星号(*) 用于通过printf的从一个参数读取这个域 。例如 printf(“%1 $ d:%2 $。* 3 $ d:%4 $。* 3 $ d \ n”, hour,min,precision,sec);此类 现在不支持此机制,用于 。所以这样的精度或宽度字段 被解析静静地忽略。

所以我试图找到其他方法来实现相同的目标。

这里是我到目前为止,这是行不通的:

#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 ========== 

我的升压转换器的lambda表达式和功能的基本理解可能是缺乏的。我怎样才能使这个工作?

回答

2

我认为,对于这种情况,你会想使用boost.bind而不是boost.lambda。部分问题在于boost :: io :: group是一个函数模板,它接收并返回可变数量的对象,因此很难为函数创建适当的签名。我将创建一个带有简单签名的字符串格式化函数,然后使用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; 
} 
1

你应该再次检查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(); 
    … 
}