代码之家  ›  专栏  ›  技术社区  ›  fmuecke

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

  •  6
  • fmuecke  · 技术社区  · 17 年前

    我一直在想,怎样才能实现梦想 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*/);
    

    编辑: 非常感谢这些有趣的解决方案。 然而,我的解决办法是不使用 tr1::bind 这是VisualStudio2008功能包/SP1附带的。我不知道为什么它不能像预期的那样工作,但事实就是这样( even MS admits that it's buggy ).也许是一些 hotfixes 会有帮助的。

    使用boost::bind,一切都按预期进行,非常简单(但有时确实很混乱:)。我真的应该首先尝试boost::bind。。。

    4 回复  |  直到 16 年前
        1
  •  13
  •   Kaz Dragon    17 年前

    std::for_每个都需要一个一元函数(或者至少是一元函数的typedefs)。

    boost::bind(
        &std::reverse<std::string::iterator>,
            boost::bind(&std::string::begin, _1), 
            boost::bind(&std::string::end, _1))
    

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

    (可能需要一些元编程来确保Range&不是双重参考)

    然后在for_中使用它(当然,在将其调整为一元函数之后)。

    std::for_each(v.begin(), v.end(),
        std::ptr_fun(&reverse_range<std::string>));
    

    因为string::begin和string::end都有常量和非常量变量,所以有必要对它们进行强制转换(正如litb在我写它们来测试我的答案时发现的…+1!)。这使得它非常冗长。Typedefs可以使它更加卫生,但要坚持一行文字主题:

    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。

        2
  •  5
  •   Loki Astari    17 年前

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

    现在,您只需一行即可完成:

    std::for_each(v.begin(), v.end(), Reverser());
    
        3
  •  5
  •   Éric Malenfant    17 年前

    具有 Boost.Phoenix2 :

    std::for_each(v.begin(), v.end(), boost::phoenix::reverse(arg1));
    

    套用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"));
    }
    

    印刷品:

    olleh
    dlrow
    
        4
  •  3
  •   Marcin    16 年前

    BOOST_FOREACH( std::string& s, v )
        std::reverse( s.begin(), s.end() );
    
    推荐文章