【问题标题】:Why there is no std::copy_if algorithm?为什么没有 std::copy_if 算法?
【发布时间】:2010-11-29 17:56:15
【问题描述】:

在 C++ 中没有 std::copy_if 算法有什么具体原因吗?我知道我可以使用 std::remove_copy_if 来实现所需的行为。我认为它是在 C++0x 中出现的,但是一个简单的 copy_if 需要一个范围、一个输出迭代器和一个仿函数会很好。只是错过了,还是有其他原因?

【问题讨论】:

标签: c++ algorithm stl


【解决方案1】:

根据 Stroustrup 的“C++ 编程语言”,这只是一种疏忽。

(作为引用,在 boost 邮件列表中回答了相同的问题:copy_if

【讨论】:

  • 作为更新,C++11 标准通过添加新的copy_if 算法纠正了这一疏忽:en.cppreference.com/w/cpp/algorithm/copy
  • 是否存在将迭代器传递给一元谓词而不是传递取消引用迭代器的结果的变体?我没有看到,但这似乎是另一个疏忽。
【解决方案2】:

Stroustrup 说他们忘记了。它在 C++11 中。

但是,您可以同时使用remove_copy_if(实际上应该称为copy_if_not)和not1

【讨论】:

  • 在我看来,我总是将“remove_copy_if”翻译成“copy_except”:)
  • ...只要您愿意接受 std::not1 与函数指针不兼容。 (正如我所见,下面已经讨论过......)
【解决方案3】:

为了完整起见,如果有人用谷歌搜索这个问题,应该提到现在(C++11 后)copy if 算法。它的行为符合预期(将某个谓词返回 true 的范围内的元素复制到另一个范围)。

一个典型的用例是

std::vector<int> foo{ 25, 15, 5, -5, -15 };
std::vector<int> bar;

// copy only positive numbers:
auto it = std::copy_if (foo.begin(), foo.end(), std::back_inserter(bar), 
            [](int i){return !(i<0);
          });

【讨论】:

    【解决方案4】:

    Multiplesourcesindicate 不小心被 STL 遗漏了。

    但是,我不确定这是事实还是自我延续的神话。如果有人能指出比 Internet 上随机帖子的链接更可信的来源,我将不胜感激。

    【讨论】:

    • 这是互联网上的非随机帖子,根据它声称是 Stroustrup 发给 Boost 邮件列表的电子邮件而被选中:lists.boost.org/Archives/boost/2001/01/8030.php。当然,这可能是一场骗局,也可能是 Stroustrup 自己买了这个神话。我想可能是 Stepanov 通常认为最好有remove_copy_if,并故意将copy_if 排除在外。但说真的,拥有remove_copy_if 而不是copy_if 显然是某种错误,如果只是一种品味:-)
    【解决方案5】:

    自己写很容易:

    template <class InputIterator, class OutputIterator, class Predicate>
    OutputIterator copy_if(InputIterator first, InputIterator last,
                           OutputIterator result, Predicate pred)
    {
      return std::remove_copy_if(first,last,result,std::not1(pred));
    }
    

    编辑:此版本适用于所有谓词:

    template <class InputIterator, class OutputIterator, class Predicate>
    OutputIterator copy_if(InputIterator first, InputIterator last,
                           OutputIterator result, Predicate pred)
    {
      while(first!=last)
      {
        if(pred(*first))
            *result++ = *first;
        ++first;
      }
      return result;
    }
    

    【讨论】:

    • 这实际上是不正确的,如 Effective STL 第 36 条所述,因为它仅适用于自适应函子。
    • 看起来并不是那么容易,您的第二次尝试似乎返回了与谓词匹配的第一个值 - 此外,恕我直言,您在这里有点离题
    • 你不需要迭代OutputIterator吗? *(result++) = *first;
    • -1:如果resultOutputIterator,那你为什么要给它分配*first?您的代码是错误的,@Peter Kovacs 是正确的。
    • @Peter & Troubadour - 当然你们都是正确的。过失。我写的代码确实有效,但大概只是因为实现细节和我的测试代码之间存在一些疯狂的交集。我已更正并为你 +1。
    【解决方案6】:

    为了完整起见,我要补充一点,对于那些不能在 boost/algorithm/cxx11/copy_if.hpp 中使用 c++11 版本(比如我)的人,boost 有 boost::algorithm::copy_if,它们将在以下情况下使用 std::copy_if

    #if __cplusplus >= 201103L
    //  Use the C++11 versions of copy_if if it is available
    using std::copy_if;         // Section 25.3.1
    #else
    

    例子:

    #include <boost/algorithm/cxx11/copy_if.hpp>
    #include <boost/assign/list_of.hpp> // for 'list_of()'
    #include <boost/foreach.hpp>
    
    #include <iostream>
    #include <vector>
    #include <iterator>
    
    struct Odd
    {
      bool operator()(int n)
      {
        return n & 1;
      }
    };
    
    int main()
    {
      std::vector<int> v = boost::assign::list_of(0)(1)(2)(3)(4);
      BOOST_FOREACH(int i, v)
        std::cout << i << ' ' ;
    
      std::vector<int> out;
      boost::algorithm::copy_if(v.begin(), v.end(), std::back_inserter(out), Odd());
    
      std::cout << std::endl;
    
      BOOST_FOREACH(int i, out)
        std::cout << i << ' ' ;
    
    }
    

    输出:

    0 1 2 3 4 
    1 3 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-26
      • 2019-10-13
      • 1970-01-01
      • 2015-04-02
      • 2017-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多