8

Dường như bộ điều hợp vòng lặp reverse_iterator định nghĩa gấp đôi hầu hết các loại lồng nhau của nó. Cụ thể, nó kế thừa công khai từ std::iterator hiển thị iterator_category, value_type, difference_type, pointerreference. Ngoại trừ iterator_categoryvalue_type, tất cả đều rõ ràng là typedef 'được chỉnh sửa lại trong định nghĩa lớp học.Tại sao reverse_iterator lại định nghĩa gấp đôi các kiểu lồng nhau của nó?

24.5.1.1 Lớp mẫu reverse_iterator [reverse.iterator]

namespace std { 
template <class Iterator> 
class reverse_iterator : public 
    iterator<typename iterator_traits<Iterator>::iterator_category, 
    typename iterator_traits<Iterator>::value_type, 
    typename iterator_traits<Iterator>::difference_type, 
    typename iterator_traits<Iterator>::pointer, 
    typename iterator_traits<Iterator>::reference> { 
public: 
    typedef Iterator           iterator_type; 
    typedef typename iterator_traits<Iterator>::difference_type difference_type; 
    typedef typename iterator_traits<Iterator>::reference  reference; 
    typedef typename iterator_traits<Iterator>::pointer   pointer; 
    // ... rest of the class 
}; 

Câu hỏi: tại sao định nghĩa lặp đi lặp lại? Đây có phải chỉ dành cho mục đích giải trình, hoặc có nhiều hơn không? Và tại sao không xác định lại iterator_categoryvalue_type?

+4

Nó cũng không xác định lại 'value_type'. Dù sao, câu hỏi này sẽ sớm trở thành tranh luận, nhờ vào [LWG 2438] (http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2438). –

+0

@ T.C. cảm ơn vì đã đào bới DR đó. Tôi cập nhật Q. Nếu bạn làm cho nó một câu trả lời, tôi sẽ chấp nhận. – TemplateRex

+5

Có thể nó phải làm với tra cứu tên phụ thuộc? Các tên được kế thừa từ 'iterator' không hiển thị trong mọi trường hợp, vì nó là một lớp cơ sở phụ thuộc. – dyp

Trả lời

6

Trong một thời gian hiện tại, chúng đã chuyển từ sử dụng std::iterator làm lớp cơ sở và hướng tới việc chỉ định rằng mỗi trình lặp phải xác định tên loại chính xác.

Khi chúng chỉ định lớp cơ sở trong tiêu chuẩn, ràng buộc việc triển khai thực hiện lớp như vậy, mặc dù mục đích thực sự là chỉ định rằng trình vòng lặp cần xác định một số tên. Cụ thể, bạn có thể is_base_of để xác định xem std::iterator là một lớp cơ sở của std::reverse_iterator. Không, không có gì đa hình, vì vậy nó khá ngớ ngẩn và vô nghĩa để làm như vậy, nhưng nếu bạn làm như vậy, tiêu chuẩn hiện tại nói rằng nó phải trả về true. Có vẻ như (với tôi) như thế này là nhiều hơn hoặc ít hơn một nửa điểm ngẫu nhiên trong quá trình di chuyển từ (nhiều hơn hoặc ít hơn vô tình) yêu cầu sử dụng std::iterator làm lớp cơ sở và chỉ định các tên phải được xác định trong std::reverse_iterator (và các trình lặp khác nhau, tất nhiên).

Đối với những người quan tâm, lịch sử của điều này bao gồm:

N3931
Issue 2438

Ngoài ra còn có văn bản thảo luận để có liên quan về ti unary_function và binary_function:

N3145
N3198

Đây là p rovided cho gần như cùng một lý do như std::iterator (tức là, chỉ để cung cấp một số typedefs trong một lớp học có nguồn gốc) vì vậy lý do đằng sau việc loại bỏ chúng là khá thích hợp để ngừng sử dụng std::iterator như một lớp cơ sở.

+0

Tricky để gọi 'is_base_of ' không phải là loại. ;) Khi sử dụng 'std :: iterator' bản thân mình, tôi có xu hướng kéo vào các định nghĩa mà tôi sử dụng, vì tôi không thể sử dụng chúng trong nội bộ (do tra cứu tên phụ thuộc) nếu tôi là một bản mẫu. – Yakk

+0

Định nghĩa của 'reverse_iterator' đã giống như thế này trong C++ 03 IS. – dyp

+0

@dyp: Với trạng thái của Google Groups nữa, tôi không chắc mình có thể tìm thấy nó, nhưng tôi nhớ một chuỗi Usenet có vẻ như khoảng năm 1996, đã cho rằng đây là một ý tưởng tồi và các typedef chỉ nên được chỉ định trực tiếp. –

3

Đây là suy đoán nhiều hơn, nhưng tất cả những kiểu khai báo thừa typedefs được sử dụng trong đặc tả của nội dung lớp là reverse_iterator. Ví dụ (C++ 03 IS):

pointer operator->() const; 
reference operator[](difference_type n) const; 

Kể từ iterator<..> là một lớp cơ sở phụ thuộc, nó sẽ không được tìm kiếm tên pointerreference.Vì vậy, typedef ing những tên làm spec còn lại đơn giản hơn:

typename iterator_traits<Iterator>::pointer operator->() const; 
typename iterator_traits<Iterator>::reference operator[](typename iterator_traits<Iterator>::difference_type n) const; 

Mặt khác, value_type không xuất hiện trong cơ thể lớp, do đó nó không cần một dư thừa typedef.

+0

Tất nhiên, điều này không trả lời câu hỏi tại sao lại xuất phát từ 'iterator' ngay từ đầu .. nhưng một khi được đưa ra,' typedef' là một hàm ý để thuận tiện. – dyp

+0

Kiểu trả về của 'toán tử []' không được chỉ định trong C++ 14 IS, btw. – dyp

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