2009-09-19 17 views
62

Czy istnieje jakiś szczególny powód, dla którego nie ma algorytmu std :: copy_if w C++? Wiem, że mogę użyć std :: remove_copy_if, aby osiągnąć wymagane zachowanie. Myślę, że nadchodzi w C++ 0x, ale prosty copy_if, który ma zasięg, iterator wyjściowy i funktor byłby miły. Czy to było po prostu pominięte, czy jest jakiś inny powód?Dlaczego nie ma algorytmu std :: copy_if?

+0

+1 Nigdy nie myślałem o tym. – AraK

+3

Zostanie dodany do następnego standardu. Obecny projekt ma go w rozdziale 25.2.1 w bibliotece algorytmów. –

+0

Duplikat: http://stackoverflow.com/questions/794320/are-they-adding-copyif-to-c0x –

Odpowiedz

41

Zgodnie z "Językiem programowania w C++" Stroustrupa było to tylko przesłuchanie.

(jako cytat, to samo pytanie odpowiedział przypominającego Mail-list: copy_if)

+9

Jako aktualizacja, standard C++ 11 poprawił to przeoczenie, dodając nowe 'copy_if' Algorytm: http://en.cppreference.com/w/cpp/algorithm/copy –

7

sourcesindicate że został przypadkowo pominięty przez STL.

Jednak nie jestem pewien, czy to fakt, czy też samonaprawiający się mit. Byłbym wdzięczny, gdyby ktoś wskazał źródło bardziej wiarygodne niż link do losowego postu w Internecie.

+3

Oto nieprzypadkowy post w Internecie, wybrany na podstawie tego, że twierdzi, że jest e-mailem od Stroustrup do listy mailingowej Boost: http://lists.boost.org/Archives/boost/2001/01/8030.php. Oczywiście może to być oszustwo, albo może Stroustrup sam kupił mit. Sądzę, że jest możliwe, że Stepanov ogólnie uważał, że najlepiej jest mieć 'remove_copy_if' i celowo wykluczyć' copy_if' jako redundantne.Ale poważnie, to jest jakaś pomyłka mieć 'remove_copy_if' ale nie' copy_if', jeśli tylko jeden ze smaku :-) –

27

Stroustrup mówi, że zapomniał. Jest w C++ 11.

Można jednak użyć remove_copy_if (która naprawdę powinna nazywać się copy_if_not), a zamiast tego not1.

+6

Zawsze tłumaczę "remove_copy_if" na "copy_except" :) – StackedCrooked

+1

... o ile jesteś gotów zaakceptować ten standard :: not1 nie jest kompatybilny ze wskaźnikiem funkcji. (Jak widzę, zostało to omówione poniżej ...) –

7

To martwy łatwe do pisania własnych:

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

Edit: Wersja ta współpracuje ze wszystkimi orzeczników:

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; 
} 
+2

To nie jest właściwie poprawne, jak zauważono w * Effective STL * item 36, ponieważ działa tylko na funfigurowalnych funktorach. – rlbond

+0

wygląda na to, że to nie jest tak łatwe, wydaje się, że twoja druga próba zwraca pierwszą wartość zgodną z predykatem - poza tym, IMHO, jesteś trochę nie na temat tutaj – rotoglup

+0

rotoglup - Obawiam się, że nie wiesz co mówisz o. "wynik" to OutputIterator. Zrobiłem test tego kodu, który znasz. –

9

Tylko dla kompletności, w przypadku gdy ktoś google jego/jej drogę do to pytanie, należy wspomnieć, że teraz (po C++ 11) istnieje algorytm. Zachowuje się zgodnie z oczekiwaniami (kopiuje elementy w zakresie, dla którego niektóre predykaty zwraca wartość true, do innego zakresu).

Typowy przypadek użycia byłby

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); 
      }); 
1

Tylko dla kompletności dodam, że impuls ma boost::algorithm::copy_if dla tych z was, którzy nie mogą korzystać z C++ wersja 11 za (jak ja) w boost/algorithm/cxx11/copy_if.hpp który użyje std::copy_if gdy jest :

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

przykład:

#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 << ' ' ; 

} 

Wyjście:

0 1 2 3 4 
1 3 
Powiązane problemy