Wie mache ich meine Iterator-Klassen nicht wie Container-Klassen aussehen?

9

Die Prämisse

Angenommen, ich habe eine Containerklasse Box , die die inneren Klassen const_iterator und iterator enthält. Weil ich möchte, dass ein iterator zu einem const_iterator castbar ist, erbt letzterer vom ersteren:

%Vor%

Das Problem

Nun möchte ich diese Klassen mit Google Test testen. Lassen Sie uns behaupten, dass die begin() und end() nicht die gleiche Sache zurückgeben:

%Vor%

Sag Hallo zu einem Kompilierfehler:

  • Klang: no member named 'begin' in 'Box::const_iterator'
  • g ++: ‘const class Box::const_iterator’ has no member named ‘begin’

Die Ursache

Einige Recherchen haben mich zu dieser Vorlage geführt im Google Test-Quellcode (folgen Sie dem Link für die erweiterte Dokumentation):

%Vor%

Das Ergebnis dieser Template-Magie ist, dass, wenn Argumente für EXPECT_* die Klassen iterator und const_iterator Member haben, der Typ als eine Container-Klasse angenommen wird. Google Test kann so gut lesbare Berichte erstellen, wenn die Erwartungen nicht erfüllt werden. Das ist nett.

Allerdings gibt es dieses kleine Detail:

%Vor%

Wenn ich die Dinge richtig verstehe, bedeutet das,

  • Box::const_iterator hat sich selbst als Mitgliedsklasse mit dem Namen const_iterator und std::iterator als Mitgliedsklasse mit dem Namen iterator .
  • Box::iterator hat sich selbst als Mitgliedsklasse mit dem Namen iterator und Box::const_iterator als Mitgliedsklasse namens const_iterator .

Daher sehen beide Iterator-Klassen wie Container-Klassen für Google Test aus!

Die Frage

Wie gestalte ich meine Iterator-Klassen so, dass sie nicht wie Container aussehen?

Dinge, die ich versucht habe:

  • Deklaration der Oberklasse std::iterator von const_iterator als private . Das behebt das Problem für const_iterator , indem die iterator -Memberklasse ausgeblendet wird, aber es lässt mich weiterhin nicht a.begin() als Parameter an EXPECT_NE übergeben, außer a ist const . Es scheint, als ob Google Test iterator begin() anstatt const_iterator begin() const aus irgendeinem Grund verwendet.
  • Entfernen der% superclass std::iterator insgesamt. Ist das eine schlechte Idee? Ich nehme an, dass ich meine std::iterator_traits manuell deklarieren muss. Gibt es sonst noch etwas, das ich verliere, wenn ich std::iterator nicht erweitere?
  • Deklaration der Oberklasse Box::const_iterator von Box::iterator als private . Dies kann oder kann keine Option sein, da ich Methoden neu deklarieren müsste, die ich lieber wiederverwenden möchte (z. B. operator++ ).

Gibt es noch etwas, was ich übersehen habe?

Das Beispiel

%Vor%     
Emil Lundberg 13.10.2014, 19:01
quelle

1 Antwort

1

ThreeInts::iterator sollte nicht von ThreeInts::const_iterator erben, stattdessen sollten sie separat implementiert werden.

%Vor%

Das Problem scheint zu sein, dass sonst ThreeInts::const_iterator beide Mitglieder namens const_iterator und iterator (aka die Konstruktoren) haben. Das iterator von const_iterator zu erben ist auch nicht const-korrekt, da const_iterator nur einen Zeiger / ähnlich zu const data enthalten sollte. STL-Container halten auch die beiden Iteratoren getrennt.

In diesem Code würde es wahrscheinlich ausreichen, statt Iteratorklassen zu definieren, einfach

zu definieren %Vor%     
tmlen 20.10.2014, 20:02
quelle

Tags und Links