我正在徘徊如何使用单个for_each命令在一个“简单”行中调用包含在向量中的字符串.
是的,我知道使用自定义函子很容易,但我不能接受,使用bind无法完成(至少我不能这样做).
#include <vector> #include <string> #include <algorithm> std::vector<std::string> v; v.push_back("abc"); v.push_back("12345"); std::for_each(v.begin(),v.end(),/*call std::reverse for each element*/);
编辑:
非常感谢那些神奇的解决方案.
但是,我的解决方案是不使用Visual Studio 2008功能包/ SP1附带的tr1::bind.我不知道为什么它不能像预期的那样起作用,但这就是它的方式(even MS admits that it’s buggy).也许一些hotfixes会有所帮助.
使用boost :: bind,一切都按照需要运行,并且非常简单(但有时候非常混乱:)).我真的应该首先尝试boost :: bind …
解决方法
std :: for_each期望一元函数(或至少具有一元函数的typedef的函数).
的std ::反向<>是一个二元函数.它需要两个迭代器.可以使用boost :: bind将它们绑定在一起,但这将是一个非常可怕的混乱.就像是:
boost::bind( &std::reverse<std::string::iterator>,boost::bind(&std::string::begin,_1),boost::bind(&std::string::end,_1))
我认为更好的是编写一个名为reverse_range的可重用函数,如下所示:
template <class Range> void reverse_range(Range& range) { std::reverse(range.begin(),range.end()); }
(可能需要一些元编程来确保Range&不是双引用)
然后在你的for_each中使用它(当然,在将它调整为一元函数之后).
std::for_each(v.begin(),std::ptr_fun(&reverse_range<std::string>));
编辑:
因为string :: begin和string :: end都有const和非const变体,所以必须抛出它们(因为我在写它们时发现了litb来测试我的答案…… 1!).这使得它非常冗长. Typedef可以使它更卫生,但要坚持单线主题:
boost::bind( &std::reverse<std::string::iterator>,boost::bind( (std::string::iterator (std::string::*)())&std::string::begin,boost::bind( (std::string::iterator (std::string::*)())&std::string::end,_1) ) );
这只是为重构而尖叫.
最后,因为我很无聊,C 0x的奖励积分:
std::for_each(v.begin(),v.end() [](std::string& s){ std::reverse(s); });
编辑:boost :: bind工作正常,不需要boost :: lambda.