使用for_each和bind反转向量中的字符串

时间:2009-09-30 09:38:44

标签: c++ stl vector tr1 stl-algorithm

我正在徘徊如何使用单个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 ...

4 个答案:

答案 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)

使用Boost.Phoenix2

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() );