我正在徘徊如何使用单个string
命令在一条“简单”的行中尊重vector
中包含的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 ...
答案 0 :(得分:13)
std :: for_each期望一元函数(或至少具有一元函数的typedef的函数)。
的std ::反向&LT;&GT;是一个二元函数。它需要两个迭代器。可以使用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&amp;不是双引用)
然后在你的for_each中使用它(当然,在将它调整为一元函数之后)。
std::for_each(v.begin(), v.end(),
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, _1),
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。
答案 1 :(得分:5)
您必须滚动自己的反向对象:
struct Reverser
{
void operator()(std::string& value) const
{
std::reverse(value.begin(),value.end());
}
};
现在你可以一行:
std::for_each(v.begin(), v.end(), Reverser());
答案 2 :(得分:5)
std::for_each(v.begin(), v.end(), boost::phoenix::reverse(arg1));
用mr-edd来解释:可测量的awesomer:)
完整示例:
#include <boost/spirit/home/phoenix.hpp>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <iterator>
int main(void)
{
using namespace boost::phoenix::arg_names; // for "arg1"
std::vector<std::string> v;
v.push_back("hello");
v.push_back("world");
std::for_each(v.begin(), v.end(), boost::phoenix::reverse(arg1));
std::copy(v.begin(), v.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
}
打印:
olleh
dlrow
答案 3 :(得分:3)
也可以使用BOOST_FOREACH宏完成:
BOOST_FOREACH( std::string& s, v )
std::reverse( s.begin(), s.end() );