Kompilierfehler im Bsp. aus dem ACCU Artikel "Defining Visitors Inline in Modern C++"



  • Ich habe den Code aus dem Artikel Defining Visitors Inline in Modern C++ versucht einzubinden weil ich die Idee interessant finde.
    Mit Visual Studio 2013 läuft alles rund, mit dem gcc4.8.2 (auch 4.8.1) führt der Beispiel Code zu einem Kompilierfehler.

    Edit:
    ➡ Ich vermute, dass es mit gcc Version 4.9.x funktioniert - zumindest sollte es das laut Artikel.
    ➡ Ich vermutete falsch - auch mit gcc Version 4.9.2 führt es zu besagtem Kompilierfehler.

    Den Code, abzüglich Fehler, aber inklusive der Fehlermeldung ist bei Ideone.com zu finden (ich verzichte deshalb auf eine Wiederholung):
    https://ideone.com/WLmPEs

    Ich verstehe nicht warum der Code dem gcc missfällt. Kann jemand mir - oder noch besser dem gcc - auf die Sprünge helfen?

    Edit:
    Hier die nachbearbeitete Fehlermeldung (ich habe alle Lambdas und std::pair<..> s entfernt, da sie keine Rolle spielen).

    prog.cpp: In instantiation of ‘struct ComposeVisitor<Triangle, .., EmptyVisitor<PolygonVisitor>::Inner, .. >::Inner’:
    prog.cpp:45:12: required from ‘struct ComposeVisitor<Square, .., ComposeVisitor<Triangle, .., EmptyVisitor<PolygonVisitor>::Inner, .. >::Inner, .. > >::Inner’
    prog.cpp:133:22: required from here
    prog.cpp:81:11: error: cannot allocate an object of abstract type ‘ComposeVisitor<Triangle, .., EmptyVisitor<PolygonVisitor>::Inner, .. >::Inner’
    Inner end_visitor()
    ^
    prog.cpp:45:12: note: because the following virtual functions are pure within ‘ComposeVisitor<Triangle, .., EmptyVisitor<PolygonVisitor>::Inner, .. >::Inner’:
    struct Inner : public BaseInner
    ^
    prog.cpp:15:18: note: virtual void PolygonVisitor::visit(Square&)
    virtual void visit(Square& sq) = 0;

    Dass EmptyVisitor::Inner von VisitorBase (= PolygonVisitor ) ableitet, aber keine der visit(..) Methoden überschreibt sollte doch auch zu Problemen führen - tut es aber zumindest und Visual Studio 2013 nicht. Vielleicht hat jemand eine Erklärung dafür?

    Edit:
    ➡ Ok, EmptyVisitor::Inner stellt einfach die pure-virtual Methoden vom Visitor-Interface zur Verfügung (etwas prosaisch ausgedrückt).

    Ausserdem bin ich an Alternativen interessiert?!? Loki scheint etwas in der Art zu bieten, allerdings möchte ich keine zusätzliche Abhängigkeit schaffen.


  • Mod

    Bevor ich's mir anschau: Ich tippe auf ill-formed NDR.



  • Aktueller Workaround für mich:
    Die Methoden im Visitor nicht pure-virtual, sondern nur virtual machen.


  • Mod

    gcc hat wahrscheinlich recht.
    Einfachster Workaround: modifiziere end_visitor

    template <typename U=Inner>
    U end_visitor()
    {
        return U(move(m_args));
    }
    

    Abstrakte Klassen dürfen nicht als Rückgabetypen von Funktionen auftreten.
    Compiler verhalten sich allerdings unterscheidlich, wenn die Tatsache, dass eine Klasse abstrakt ist, bei der Funktionsdeklaration nicht bekannt ist.

    struct X;
    X foo();
    struct X { void bar() = 0; }; // Deklaration von foo wird nachträglich ill-formed
    

    gcc ist hier traditionell recht streng.

    Bei der Instantiierung einer Templateklasse werden auch die Deklarationen aller Member instantiiert.
    CompositeVisitor<...,EmptyVisitor<...>:Inner,...>>::end_visitor wir nie instantiiert, aber die Deklaration als solche ist ill-formed sobald Inner instantiiert wird.



  • Vielen Dank! Das funktioniert.

    Edit:
    Danke auch für die Erklärung.


Anmelden zum Antworten