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/WLmPEsIch 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 undstd::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::InnervonVisitorBase(=PolygonVisitor) ableitet, aber keine dervisit(..)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::Innerstellt 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.
-
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.
-
gcc hat wahrscheinlich recht.
Einfachster Workaround: modifiziere end_visitortemplate <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-formedgcc 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.