2012-12-27 15 views
7

W jaki sposób zdefiniować iteratory forward-output-iterators w C++ 11 w sposób kanoniczny?Kanoniczny sposób definiowania wyjściowego Iteratora wyjściowego

Zgodnie ze standardem parametr forward_iterator jest tylko parametrem input_iterator. Tak więc odpowiadający forward_iterator_tag rozszerza tylko input_iterator_tag. Jeśli używamy std::iterator do zdefiniowania naszych iteratorów, jakiego tagu używamy do forward-output-iteratora?

Czy można zdefiniować prywatny znacznik rozszerzający zarówno forward_iterator_tag, jak i output_iterator_tag lub czy istnieje lepsze rozwiązanie?

+0

dziedziczenie z nich obu będzie –

+0

Jako pytanie boczne: czy ktoś wie, czy te zmienne znaczniki iterator zostały uznane za standardową bibliotekę? A jeśli tak, dlaczego nie zostały uwzględnione? –

Odpowiedz

6

Kanoniczną rzeczą do zrobienia jest dziedziczenie tylko od std::iterator<std::forward_iterator_tag, T>. Iteratory mają tylko jedną kategorię.

Standard nie ma algorytmów (ani innych zastosowań) dla iteratora wyjścia, który jest również iteratorem forward. Wszystkie zastosowania iteratorów wyjściowych w standardzie wymagają tylko pojedynczego przejścia.

Zamiast tego standard ma koncepcję mutowalnych i niezmiennych iteratorów kategorii forward/bidi/randomaccess. Wszystkie algorytmy, które muszą pisać przez iteratory, i które wymagają więcej niż jednoprzebiegowy, również czytają te same iteratory, przez które piszą. To jest std::remove, std::sort i inne algorytmy mutowania.

Różnica między iteratorami zmiennymi a niezmiennymi nie jest wykrywana przez znacznik iteratora, zależy to od tego, czy wyrażenia przypisania są poprawnie sformułowane. Na przykład, jeśli przekażesz iteratorowi do std::sort, który jest niezmienny, to algorytm i tak nie będzie się kompilował, więc generalnie nie ma potrzeby, aby iterator wejściowy był również oznaczony jako output_iterator_tag. Wszystkie algorytmy, które wymagają OutputIterator po prostu będą pracować z zmiennym ForwardIterator, znowu nie ma potrzeby, aby był oznaczony output_iterator_tag.

Jeśli masz inne potrzeby niż standardowe algorytmy, nie mogę od razu pomyśleć o tym, że twoja propozycja nie zadziała dla twoich iteratorów. Ale nie wykryje zmiennego standardowego iteratora. Na przykład std::deque<int>::iterator i int* mają kategorię iteratora random_access_iterator_tag, a nie swój prywatny znacznik i nie mają nic wspólnego z output_iterator_tag. Więc lepiej byłoby lepiej zdefiniować własną klasę cech, niż mieć nadzieję na dostosowanie istniejącego iterator_traits::iterator_category, aby zapewnić pożądane informacje.

+0

Dzięki! To wyjaśniło sporo. Ostatecznie oznacza to, że niezmienne iteratory zwracają stałe referencje/kopie wskazanego elementu, aby zapobiec przypisaniu przez zwróconą referencję, prawda? – MFH

+1

@MFH: Właśnie. Niezmienne iteratory nad kontenerami zwracają "const T &" (nie sprawdziłem, czy jest to rzeczywiście wymagane, lub czy mogą zamiast tego zwracać proxy). Inne niezmienne iteratory mogą zwrócić wszystko, co można przekształcić na 'T'. –

Powiązane problemy