2011-11-17 8 views
14

Thuật toán STL độc lập (như std::count_if) lấy cặp lặp. Trong mọi trường hợp mà tôi sử dụng những người (và trong tất cả các ví dụ tôi đã nhìn thấy trực tuyến!), Tôi thấy mình gõThuật toán STL lấy toàn bộ vùng chứa chứ không phải là .begin(), end() là arg?

std::count_if(myContainer.begin(),myContainer.end(), /* ... */); 

Có một lý do tại sao các mẫu viết tắt của phong cách

std::count_if(myContainer, /* ... */); 

không cung cấp, cho rằng nhiều hơn không phải là operaation thực hiện trên toàn bộ container? Tôi đã bỏ qua nó? Câu trả lời có khác với C++ 11 và C++ 03 không?

+2

Đây là một quyết định thiết kế đơn giản. Nhiều người không tìm thấy nó như một sự lựa chọn tốt (xem http://www.slideshare.net/rawwell/iteratorsmustgo). Boost cung cấp các thuật toán đó bằng cách sử dụng khái niệm Phạm vi của chúng. – visitor

Trả lời

10

Có một đẹp blog-post bởi Herb Sutter thảo luận về các câu hỏi . Ý chính là việc thêm quá tải container cho các thuật toán có thể tạo ra sự mơ hồ nếu quá tải cho thuật toán đó với cùng số lượng các tham số mẫu đã tồn tại. Các khái niệm nhằm khắc phục vấn đề đó.

+0

Ok, sau đó 'std :: count_if_all' hoặc' std :: count_all_if' sẽ thực hiện công việc? Tương tự với 'std :: sort' (' std :: sort_all') và tất cả những thứ khác ... –

0

Đơn giản vì thuật toán STL được kết nối/đàm phán với vùng chứa bằng trình lặp.

2

Một lý do có thể là để cung cấp tính linh hoạt cho dải vòng lặp. Bạn có thể không cần để lặp qua tất cả các yếu tố đôi khi:

<iterator> it = myContainer.begin(); 
it++; // do something 
it++; // do something 
... 
std::count_if(it, myContainer.end(), /* ... */); 

Ngoài ra, bạn luôn có thể có một wrapper mà thực hiện điều này cho bạn:

template<typename T> 
... count_if (T myContainer, ...) 
{ 
    std::count_if(myContainer.begin(), myContainer.end(), /* ... */); 
} 
+2

Trong C++ 11, sử dụng 'begin (myContainer)' và 'end (myContainer)' để làm cho nó hoạt động với các mảng. – Sjoerd

+1

0,1% -case nơi bạn cần phải lặp lại chỉ trên một phần của container để đánh máy '.begin()' và '.end()' trong 99,9% trường hợp, nếu có thể có cả hai. – eudoxos

+1

@Euxodos: Có, 0,1% các trường hợp đó sẽ được giải quyết một cách trivially với 'count_if (make_range (it, myContainer.end()), /*...*/);'. - Về mặt lịch sử, có vẻ như các thuật toán đã được thêm vào thư viện chuẩn một cách nhanh chóng, và lặp lại là một ý tưởng mới lạ tại một thời điểm. Nếu họ có nhiều kinh nghiệm hơn với họ, mọi thứ có thể đã trở nên khác biệt. Nhưng bây giờ có vẻ như, họ không thể buông bỏ những điều cũ, và không thể thêm những điều mới, trừ khi nó có thể được thực hiện một cách sạch sẽ. – UncleBens

2

Nguyên tắc và tính linh hoạt của STL chủ yếu là do hoạt động trên các trình vòng lặp thay vì các vùng chứa. Đây không phải là vấn đề lớn, bạn có thể sử dụng lại mẹo tôi đang sử dụng từ những năm đầu của tôi:

#define FULL_RANGE(c) (c).begin(), (c).end() 

std::copy(FULL_RANGE(c), std::ostream_iterator<c::value_type>(cout, "\n")); 
+0

Đó là một mẹo thông minh thực sự, mặc dù tôi có thể gọi nó là ALL và ngày nay sử dụng std :: begin và std :: end –