8

Es scheint, dass der Iteratoradapter reverse_iterator die meisten seiner verschachtelten Typen doppelt definiert. Insbesondere erbt es öffentlich von std::iterator, das iterator_category, value_type, difference_type, pointer und reference exponiert. Mit Ausnahme von iterator_category und value_type sind dies alle explizit typedef 'wieder in der Klassendefinition.Warum definiert reverse_iterator seine verschachtelten Typen doppelt?

24.5.1.1 Vorlage Klasse 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 
}; 

Frage: warum die wiederholte Definition? Ist das nur für die Zwecke der Exposition oder gibt es mehr dazu? Und warum nicht iterator_category und value_type neu definieren?

+4

Es definiert auch nicht "value_type". Wie auch immer, diese Frage wird bald hoffnungslos werden, dank [LWG 2438] (http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2438). –

+0

@ T.C. Danke für das Ausgraben dieser DR. Ich habe das Q aktualisiert. Wenn du eine Antwort machst, akzeptiere ich. – TemplateRex

+5

Vielleicht hat es mit abhängiger Namenssuche zu tun? Die von 'iterator' übernommenen Namen sind nicht in allen Fällen sichtbar, da es sich um eine abhängige Basisklasse handelt. – dyp

Antwort

6

Seit einiger Zeit haben sie sich von der Verwendung von std::iterator als Basisklasse entfernt und müssen lediglich angeben, dass jeder Iterator die korrekten Typnamen definieren muss.

Wenn sie die Basisklasse im Standard angeben, werden die Implementierungen so eingeschränkt, dass die Klasse auf diese Weise implementiert wird, obwohl die einzige wirkliche Absicht darin besteht, anzugeben, dass der Iterator einige Namen definieren muss. Insbesondere könnten Sie is_base_of bestimmen, ob std::iterator eine Basisklasse von std::reverse_iterator ist. Nein, es gibt nichts polymorphes, also ist es ziemlich dumm und sinnlos, das zu tun, aber wenn Sie das tun, sagt der aktuelle Standard, dass es zurückgeben muss.

Es sieht (wie ich) aus, als wäre dies mehr oder weniger ein zufälliger Zwischenpunkt im Prozess des (mehr oder weniger zufälligen) Verschiebens von std::iterator als Basisklasse, und einfach die Namen angeben, die müssen definiert werden in std::reverse_iterator (und natürlich auch verschiedene andere Iteratoren).

Für diejenigen, die Pflege, die Geschichte dieses beinhaltet:

N3931
Issue 2438

Es gibt auch so ähnliche Diskussionspapiere über ironischen unary_function und binary_function:

N3145
N3198

Diese waren p aus ungefähr den gleichen Gründen wie std::iterator (d. h., um einige typedefs in einer abgeleiteten Klasse bereitzustellen), so dass die Gründe für ihre Entfernung ziemlich passend sind, std::iterator als Basisklasse zu verwenden.

+0

Tricky zu nennen 'is_base_of ' als beide sind Typen. ;) Wenn ich 'std :: iterator' benutze, neige ich dazu, die Definitionen, die ich benutze, einzufangen, da ich sie intern nicht benutzen kann (aufgrund der abhängigen Namenssuche), wenn ich selbst eine Vorlage bin. – Yakk

+0

Die Definition von 'reverse_iterator' war in der C++ 03 IS bereits so. – dyp

+0

@dyp: Angesichts des Zustandes von Google Groups bin ich mir nicht sicher, ob ich es finden könnte, aber ich erinnere mich an einen Usenet-Thread, der ungefähr um 1996 herum aussah und schon argumentierte, dass dies eine schlechte Idee und die Typedefs waren sollte nur direkt angegeben werden. –

3

Dies ist eher eine Vermutung, aber alle diese redundanten typedefs deklarieren Typen, die innerhalb der Spezifikation des Klassenkörpers von reverse_iterator verwendet werden. Zum Beispiel (C++ 03 IS):

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

Da iterator<..> eine abhängige Basisklasse, wird es nicht für die Namen pointer und reference gesucht werden.So typedef diese Namen ing macht die verbleibende spec einfacher:

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

Auf der anderen Seite, value_type erscheint nicht in der Klasse Körper, daher ist es nicht ein redundantes typedef benötigen.

+0

Natürlich beantwortet dies nicht die Frage, warum man von "iterator" an erster Stelle ableiten soll. Aber sobald das gegeben ist, sind die 'typedefs 'eine Implikation für die Bequemlichkeit. – dyp

+0

Der Rückgabetyp von 'operator []' ist in C++ 14 IS, btw nicht angegeben. – dyp