2009-09-19 33 views
62

Có lý do cụ thể nào để không có std :: copy_if algorithm trong C++ không? Tôi biết tôi có thể sử dụng std :: remove_copy_if để đạt được các hành vi cần thiết. Tôi nghĩ rằng nó đang đến trong C + + 0x, nhưng một copy_if đơn giản mà mất một phạm vi, một iterator đầu ra và một functor sẽ có được tốt đẹp. Nó chỉ đơn giản là bỏ lỡ hoặc là có một số lý do khác đằng sau nó?Tại sao không có thuật toán std :: copy_if?

+0

+1 Tôi chưa bao giờ nghĩ về nó. – AraK

+3

Nó sẽ được thêm vào tiêu chuẩn tiếp theo. Dự thảo hiện tại có nó trong chương 25.2.1 trong thư viện thuật toán. –

+0

Trùng lặp: http://stackoverflow.com/questions/794320/are-they-adding-copyif-to-c0x –

Trả lời

41

Theo "Ngôn ngữ lập trình C++ của Stroustrup", nó chỉ là một cảnh tượng quá mức.

(như là một trích dẫn, cùng một câu hỏi đã trả lời trong thúc đẩy thư danh sách: copy_if)

+9

Như một bản cập nhật, tiêu chuẩn C++ 11 đã sửa lại sự giám sát này bằng cách thêm một 'copy_if' mới Thuật toán: http://en.cppreference.com/w/cpp/algorithm/copy –

7

Multiplesourcesindicate rằng nó bị bỏ rơi do STL gây ra.

Tuy nhiên, tôi không chắc đó có phải là sự thật hay là một huyền thoại vĩnh viễn. Tôi sẽ đánh giá cao nếu bất cứ ai sẽ chỉ ra một nguồn đáng tin cậy hơn một liên kết đến một bài ngẫu nhiên trên Internet.

+3

Đây là bài đăng không phải ngẫu nhiên trên internet, được chọn dựa trên cơ sở mà nó xác nhận là một email từ Stroustrup vào danh sách gửi thư Boost: http://lists.boost.org/Archives/boost/2001/01/8030.php. Tất nhiên nó có thể là một gian lận, hoặc nó có thể là Stroustrup mình đã mua huyền thoại. Tôi đoán có thể là Stepanov thường nghĩ rằng tốt nhất nên có 'remove_copy_if', và cố ý loại trừ' copy_if' thành dư thừa.Nhưng nghiêm túc, rõ ràng là có một loại sai lầm nào đó để có 'remove_copy_if' nhưng không phải là' copy_if', nếu chỉ có một hương vị :-) –

27

Stroustrup nói họ đã quên nó. Đó là trong C++ 11.

Tuy nhiên, bạn có thể sử dụng remove_copy_if (thực tế nên được gọi là copy_if_not) cùng với not1 thay thế.

+6

Trong tâm trí của tôi, tôi luôn dịch "remove_copy_if" thành "copy_except" :) – StackedCrooked

+1

... miễn là bạn sẵn sàng chấp nhận điều đó :: not1 không tương thích với con trỏ hàm. (Như tôi thấy đã được thảo luận dưới đây ...) –

7

Đó là chết dễ dàng để viết riêng của bạn:

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: phiên bản này hoạt động với tất cả các vị từ:

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

Điều này không thực sự chính xác, như được ghi trong * Hiệu quả STL * mục 36, bởi vì nó chỉ hoạt động trên functors thích nghi. – rlbond

+0

có vẻ như nó không phải là chết dễ dàng, có vẻ như nỗ lực thứ hai của bạn trả về giá trị đầu tiên phù hợp với vị ngữ - bên cạnh đó, IMHO, bạn là một chút off-topic ở đây – rotoglup

+0

rotoglup - Tôi sợ rằng bạn không biết những gì bạn đang nói về. 'result' là một OutputIterator. Tôi đã kiểm tra mã này bạn biết. –

9

Chỉ cần cho đầy đủ, trong trường hợp ai đó Googles/cách của mình để câu hỏi này, cần lưu ý rằng bây giờ (bài C++ 11) một thuật toán copy if. Nó hoạt động như mong đợi (sao chép các phần tử trong một phạm vi, mà một số biến vị ngữ trả về true, đến một phạm vi khác).

Một trường hợp sử dụng điển hình sẽ là

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

Chỉ cần cho đầy đủ tôi sẽ bổ sung tăng mà có boost::algorithm::copy_if cho những người bạn của những người không thể sử dụng C++ phiên bản 11 của (như tôi) trong boost/algorithm/cxx11/copy_if.hpp mà sẽ sử dụng std::copy_if khi :

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

Ví dụ:

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

} 

Đầu ra:

0 1 2 3 4 
1 3 
Các vấn đề liên quan