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

fmu*_*cke 6 c++ stl vector tr1 stl-algorithm

我正在徘徊,如何在一条"简单"的行中使用单个命令来回避string包含在s中的内容.vectorfor_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*/);
Run Code Online (Sandbox Code Playgroud)

编辑:非常 感谢那些神奇的解决方案.但是,我的解决方案是不使用Visual Studio 2008功能包/ SP1附带的tr1 :: bind.我不知道为什么它不能像预期的那样起作用,但就是它的方式(即使MS承认它是有缺陷的).也许一些修补程序会有所帮助.

使用boost :: bind,一切都按照需要运行,并且非常简单(但有时候非常混乱:)).我真的应该首先尝试boost :: bind ...

Kaz*_*gon 13

std :: for_each期望一元函数(或至少具有一元函数的typedef的函数).

std :: reverse <>是一个二进制函数.它需要两个迭代器.可以使用boost :: bind将它们绑定在一起,但这将是一个非常可怕的混乱.就像是:

boost::bind(
    &std::reverse<std::string::iterator>,
        boost::bind(&std::string::begin, _1), 
        boost::bind(&std::string::end, _1))
Run Code Online (Sandbox Code Playgroud)

我认为更好的是编写一个名为reverse_range的可重用函数,如下所示:

template <class Range>
void reverse_range(Range& range)
{
    std::reverse(range.begin(), range.end());
}
Run Code Online (Sandbox Code Playgroud)

(可能有一些元编程以确保Range&不是双引用)

然后在你的for_each中使用它(当然,在将它调整为一元函数之后).

std::for_each(v.begin(), v.end(),
    std::ptr_fun(&reverse_range<std::string>));
Run Code Online (Sandbox Code Playgroud)

编辑:

因为string :: begin和string :: end都有const和非const变体,所以必须抛出它们(就像我在写它们时发现它们来测试我的答案...... +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)
    )
);
Run Code Online (Sandbox Code Playgroud)

这只是为重构而尖叫.

最后,因为我很无聊,C++ 0x的奖励积分:

std::for_each(v.begin(), v.end() [](std::string& s){ std::reverse(s); });
Run Code Online (Sandbox Code Playgroud)

编辑:boost :: bind工作正常,不需要boost :: lambda.

  • 我试过这个工作:`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))` (3认同)

Mar*_*ork 5

您必须滚动自己的反向对象:

struct Reverser
{
    void operator()(std::string& value) const
    {
        std::reverse(value.begin(),value.end());
    }
};
Run Code Online (Sandbox Code Playgroud)

现在你可以做一行:

std::for_each(v.begin(), v.end(), Reverser());
Run Code Online (Sandbox Code Playgroud)


Éri*_*ant 5

使用Boost.Phoenix2:

std::for_each(v.begin(), v.end(), boost::phoenix::reverse(arg1));
Run Code Online (Sandbox Code Playgroud)

解释mr-edd:可测量的美妙:)

完整示例:

#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"));
}
Run Code Online (Sandbox Code Playgroud)

打印:

olleh
dlrow
Run Code Online (Sandbox Code Playgroud)