2013-04-29 43 views
7

Theo hầu hết các tài liệu tham khảo C++, ví dụ cplusplus.com, forward iterators không bắt buộc phải được gán (ý tôi là, trì hoãn một giá trị). Tuy nhiên, đối với một số thuật toán STL rằng cần phải viết giá trị, ví dụ std::fill (còn std::generate vv), các đặc điểm kỹ thuật sử dụng mong iterator:STL điền và chuyển tiếp vòng lặp

template <class ForwardIterator, class T> 
    void fill (ForwardIterator first, ForwardIterator last, const T& val); 

trong khi hành vi tương đương đòi hỏi dereference vế trái:

template <class ForwardIterator, class T> 
    void fill (ForwardIterator first, ForwardIterator last, const T& val) 
{ 
    while (first != last) { 
    *first = val; 
    ++first; 
    } 
} 

Vì vậy, nó thực sự là sử dụng một iterator chuyển tiếp có thể thay đổi với một pass duy nhất.

Bây giờ câu hỏi là:

(1) Tại sao không làm cho nó rõ ràng rằng lặp về phía trước được sử dụng trong những trường hợp này là có thể thay đổi?

(2) Cập nhật: Tôi thấy câu hỏi sau là ngu ngốc: Tôi tạm thời quên rằng các trình vòng lặp đầu ra không cần hỗ trợ so sánh bình đẳng. Câu hỏi trên vẫn còn, anyway.

Tại sao sử dụng trình vòng lặp chuyển tiếp thay vì trình vòng lặp đầu ra cho std::fill, std::generate vv trong khi chúng không thực sự cần nhiều lần truyền? (std::copy chỉ cần lặp đầu ra, ví dụ. Lý do là gì?)

+0

'trình vòng lặp chuyển tiếp không bắt buộc phải gán ', làm cách nào bạn xác định điều đó? Tôi khá chắc chắn họ có thể chuyển nhượng được. –

+0

@ JesseGood Với mục đích thực tế, chúng hầu như luôn được gán, nhưng nếu bạn đọc tài liệu tham khảo http://cplusplus.com/reference/iterator/ForwardIterator/?kw=forward%20iterator thì không. – 4ae1e1

+1

@ JesseGood Tôi cũng tìm thấy điều này trên SO: http://stackoverflow.com/questions/14058642/are-forward-iterators-output-iterators – 4ae1e1

Trả lời

5

Từ chữ ký

template <class ForwardIterator, class T> 
void fill (ForwardIterator first, ForwardIterator last, const T& val); 

bạn không thể suy ra rằng ForwardIterator là một iterator được mô tả trong forward iterator. Tuy nhiên, nếu bạn đọc các mô tả tham số, bạn sẽ thấy rằng firstlast phải

Forward Iterators với vị trí ban đầu và cuối cùng trong một chuỗi các yếu tố có hỗ trợ được gán một giá trị của loại T.

(nhấn mạnh bởi tôi). Vì vậy, một iterator chuyển tiếp đáp ứng không có gì nhiều hơn những gì được yêu cầu của một iterator chuyển tiếp không phải là một đối số hợp lệ.

+0

Vâng, đó là một điểm tốt. Nhưng chữ ký là khó khăn từ một quan điểm tiêu chuẩn của xem. – 4ae1e1

+0

Cách khác là giới thiệu tên mới cho các trình vòng lặp chuyển tiếp hỗ trợ gán cho phần tử được trỏ tới. – Oswald

1

Điều này có vẻ không lạ lùng đối với tôi, do đặc điểm kỹ thuật cho fill là bộ lặp (không tham chiếu) có thể được gán từ T. Trình lặp đầu ra sẽ không đủ vì nó không thể so sánh để xác định phạm vi kết thúc, do đó, một yêu cầu được chọn là forward_iterator.

Bạn sẽ lưu ý rằng fill_nlàm sử dụng trình vòng lặp đầu ra vì không cần so sánh vòng lặp để xác định kết thúc chuỗi cần điền.

+0

Tôi nghĩ điểm của OP là khái niệm lặp đi lặp lại là * bắt buộc * nhưng không * đủ * để chỉ định các yêu cầu cho loại đối số. Điều tương tự cũng sẽ xảy ra với "đầu ra vòng lặp"; chỉ bằng cách yêu cầu đối số là * cả hai * chúng ta có nhận được ngữ nghĩa chính xác không. Đặt một cách khác, có các trình vòng lặp chuyển tiếp mà trên đó 'std :: fill' không thể được gọi. –

Các vấn đề liên quan