Почему нет алгоритма std :: copy_if? - PullRequest
63 голосов
/ 19 сентября 2009

Есть ли какая-либо конкретная причина отсутствия алгоритма std :: copy_if в C ++? Я знаю, что могу использовать std :: remove_copy_if для достижения требуемого поведения. Я думаю, что это происходит в C ++ 0x, но простой copy_if, который принимает диапазон, итератор вывода и функтор, был бы хорош. Было ли это просто пропущено или есть какая-то другая причина?

Ответы [ 6 ]

41 голосов
/ 19 сентября 2009

По словам Страуструпа "Язык программирования C ++", это было просто упущением.

(как цитата, тот же вопрос отвечал в буст рассылках: copy_if )

27 голосов
/ 19 сентября 2009

Страуструп говорит, что они забыли это. Это на C ++ 11.

Однако вместо этого вы можете использовать remove_copy_if (что на самом деле должно называться copy_if_not) вместе с not1.

9 голосов
/ 10 мая 2014

Просто для полноты, в случае, если кто-то ищет свой вопрос в этом вопросе, следует упомянуть, что сейчас (после C ++ 11) есть a , если копия 1005 * алгоритм. Он ведет себя как ожидалось (копирует элементы в диапазоне, для которого один предикат возвращает 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);
          });
7 голосов
/ 19 сентября 2009

Легко написать свою собственную:

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;
}
7 голосов
/ 19 сентября 2009

Несколько источников указывают , что он был случайно исключен из STL.

Однако я не уверен, является ли это фактом или самосохраняющимся мифом. Буду признателен, если кто-нибудь укажет на источник, более надежный, чем ссылка на случайный пост в Интернете.

1 голос
/ 06 сентября 2016

Просто для полноты добавлю, что boost имеет boost::algorithm::copy_if для тех из вас, кто не может использовать версию c ++ 11 (как и я) в boost/algorithm/cxx11/copy_if.hpp, которая будет использовать 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 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...