2016-03-29 3 views
3

Ich versuche zu verstehen a program demonstrating boost/spirit.Das Parsen von Konstruktorinitialisierer für Vorlage verstehen

Im folgenden Template-Definition:

template <typename Iterator> 
struct roman : qi::grammar<Iterator,unsigned()> { 
    roman() : roman::base_type(start) 
    { 
     using qi::eps; 
     using qi::lit; 
     using qi::_val; 
     using qi::_1; 
     using ascii::char_; 

     start = eps[_val = 0] >> 
      (
       +lit('M')[_val += 1000] 
       || hundreds[_val += _1] 
       || tens[_val += _1] 
       || ones[_val += _1] 
       ) 
      ; 
    } 

    qi::rule<Iterator,unsigned()> start; 
}; 

Ich versuche, die Bedeutung von : roman::base_type(start) zu verstehen.

  • Ich nehme an, es ist ein constructor initializer.
  • Außerdem gehe ich davon aus, dass es sich um eine member initializer list und
    • , dass das Mitglied-initializer roman::base_type(start) eine Basis von romanbase_type
    • die eigentlich für grammar<Iterator, T1, T2, T3, T4> aus dem roman erbt ein typedef aufgerufen initialisiert.

Was ich nicht verstehe ist, wie es mit start initialisiert werden kann, wenn start Mitglied von roman ist, die abgeleitete Klasse wir konstruieren noch?

+2

Möglicherweise benötigt der Basisklassenkonstruktor nur einen Verweis auf ein 'qi: rule <>' -Objekt, um daran zu binden, und verwendet es nicht sofort? Dann kann der Konstruktor das 'start'-Memberobjekt initialisieren, so dass es für die Verwendung bereit ist, wenn die Basisklasse es benötigt. – CiaPan

+0

@CiaPan Ja, das stimmt, der Konstruktor nimmt nur eine Referenz: 'Grammatik (Regel const &, std :: Zeichenkette const & =" unbenannte-Grammatik ")'. Also sind die Adressen der abgeleiteten Mitglieder bereit, als Referenz genommen zu werden, während die Basen noch initialisiert werden? – wally

+0

Ja. Das Objekt wird zuerst zugewiesen, dann konstruiert, so dass während der 'roman()' -Konstruktor-Prolog-Ausführung das 'start'-Element bereits zugewiesen ist, daher ist der Verweis darauf schon bekannt. Die Funktionen können sie übergeben und sicher speichern, sofern sie nicht versuchen, sie zu dereferenzieren (verwenden Sie das Objekt tatsächlich). – CiaPan

Antwort

2

Aus der Erzählung um das Beispiel in der Dokumentation:

  1. der Basisgrammatik Klasse initialisieren, indem er die Startregel (seine die erste Regel geben, die, wenn sie aufgerufen wird die Grammatik beginnt das Parsen)

Quelle: http://www.boost.org/doc/libs/1_60_0/libs/spirit/doc/html/spirit/qi/tutorials/roman_numerals.html

Es ist eine Referenz auf das Element übergeben. Obwohl das Element zu diesem Zeitpunkt nicht konstruiert ist, ist der Verweis darauf gültig. Sofern die Basisklasse die Referenz nicht dereferenziert (d. H. Nur speichert oder ihre Adresse nimmt), ist der Code legal ... wenn ein wenig "gefährlich".

+0

Es scheint fast ... magisch. Ich mag es, aber gibt es eine bestimmte Verordnung im Standard, die erklärt, wie die Mitgliedsadressen an diesem Punkt verwendbar sind? Oder hat jemand [legal] gemacht (http://imgur.com/gallery/eKfQdxY)? – wally

+1

§9.2 (2) ist der nächste, den ich zu einer Erwähnung finden kann, gekoppelt mit den Regeln für die Initialisierungsreihenfolge, ich glaube, es ist erfassbar: Eine Klasse wird als vollständig definierter Objekttyp (3.9) (oder vollständiger Typ) betrachtet Schließen} des Klassenspezifizierers. Innerhalb der Klassenmember-Spezifikation wird die Klasse in Funktionskörpern als vollständig betrachtet, Standardargumente, using-declarations, die eritierende Konstruktoren (12.9), exception-specifications und brace-or-equal-initializer für nicht-statische implementieren Datenelemente (einschließlich solcher Dinge in verschachtelten Klassen). Ansonsten es gilt als unvollständig ... –

+1

Natürlich ist das legal. Sie können die Adresse eines Mitglieds übernehmen, sobald eine Adresse des enthaltenden Objekts vorhanden ist. Die Initialisierung kommt zu einem späteren Zeitpunkt und ist kein Problem, solange die Basis nicht annimmt, während der Konstruktion von _it Methoden für die Referenz aufzurufen. Es gibt noch schlimmer: http://www.boost.org/doc/libs/1_60_0/libs/utility/doc/html/base_from_member.html – sehe