Ich würde gerne einen boost.variant<T0,T1,T2>
als Parameter für eine Vorlage 'Besucher'-Klasse verwenden, die Besucher-Operatoren wie vom bosch.variant Besucher-Mechanismus benötigt, in diesem Fall alle zurückgebenden Void, d. h.
Die Vorlage hätte auch für jede der Typen T0 ... in der Variante eine entsprechende virtuelle Funktion, die standardmäßig nichts tut. Der Benutzer kann von der Vorlagenklasse erben und nur die virtuellen Funktionen neu definieren, an denen er interessiert ist. Dies ähnelt dem bekannten Template-Muster. Die einzige Lösung, die mir gelungen ist, ist, die boost :: variant und den zugehörigen Besucher in eine einzige Vorlage zu packen und über typedefs darauf zuzugreifen. Das klappt gut, fühlt sich aber etwas klobig an. Hier ist der Code:
%Vor%Die Klasse wird dann wie folgt verwendet:
%Vor%Wie ich schon sagte, scheint das okay zu sein, aber ich würde es vorziehen, wenn ich keine spezielle Wrapper-Klasse erstellen müsste, um die Variante und den Besucher zusammen zu binden. Ich wäre lieber in der Lage, eine boost.variant direkt zu verwenden, um die Vorlage Besucher Klasse zu instanziieren. Ich habe mir die Verwendung von Typparametern, Nicht-Typparametern und Template-Template-Parametern angesehen, aber es scheint sich nichts zu empfehlen. Ist das was ich versuche nicht möglich? Ich kann etwas vermissen, und würde es schätzen, wenn jemand etwas dazu hat.
Der Code mit Boost Variant und virtuellem Versand ist ein wenig faul. Vor allem wenn man bedenkt, dass Sie wissen, woran Sie während der Kompilierung interessiert sind und dass Sie zur Laufzeit keine virtuelle Tabelle erstellen müssen, um Ihre Ziele zu erreichen.
Ich würde Ihnen empfehlen, partielle Template-Spezialisierung zu verwenden. Also, haben Sie eine Standard-Template-Methode, die jeden Typ in der Variante akzeptieren kann und nichts tun wird. Für diejenigen Arten, die Sie interessieren, nur Vorlage zu spezialisieren.
Hier ist ein Beispiel. Wir haben drei Arten - Foo, Bar und War. Wir sind nur an den letzten beiden Typen interessiert und haben eine Spezialisierung für sie. Also wird Foo ignoriert.
%Vor%Hier ist ein einfaches Beispiel für die Verwendung:
%Vor%Die Ausgabe dieses Programms lautet:
%Vor%Hier ist eine andere Lösung. Wir erstellen einen Standardbesucher, der alles außer dem, was Sie in einer Typenliste angegeben haben, ignoriert. Es ist nicht so praktisch, weil Sie eine Liste von Typen zweimal angeben müssen - einmal in einer Typenliste und dann in jeder Verarbeitungsmethode (Operator). Außerdem erbt die generische Vorlage tatsächlich Ihren Besucher. Aber trotzdem, hier gehen wir:
%Vor%Mit der Zeit entwickeln sich neue und interessante Bibliotheken. Diese Frage ist alt, aber seitdem gibt es eine Lösung, die für mich persönlich weit überlegen ist, was bisher gegeben wurde.
Die ausgezeichnete Mach7 -Bibliothek, die noch nie dagewesene (und damit besuchende) Möglichkeiten bietet. Es wurde von Yuriy Solodkyy, Gabriel Dos Reis und Bjarne Stroustrup selbst geschrieben. Für diejenigen, die über diese Frage stolpern, hier ein Beispiel aus der README:
%Vor%Ich arbeite jetzt damit und bisher ist es eine wahre Freude zu benutzen.
Tom, ich glaube, dass Ihre Frage in einem bestimmten Kontext viel Sinn ergibt. Angenommen, Sie möchten Besucher verschiedener Typen in einem Vektor speichern. Dies ist jedoch nicht möglich, da alle Typen unterschiedlich sind. Sie haben einige Möglichkeiten: Verwenden Sie die Variante erneut, um Besucher zu speichern, boost.any zu verwenden oder virtuelle Funktionen zu verwenden. Ich denke, dass virtuelle Funktionen hier eine elegante Lösung darstellen, aber sicherlich nicht die einzige.
Hier ist, wie es geht.
Zuerst wollen wir eine Variante verwenden; bool
, int
und float
werden tun.
Dann kommt die Basisklasse, mehr oder weniger wie du sie hattest.
%Vor%
Als nächstes haben wir zwei spezifische Varianten.
%Vor%
Schließlich können wir einen einzelnen Vektor mit verschiedenen Varianten erstellen:
%Vor%
Und hier ist die Ausgabe:
%Vor%Wenn ich aus irgendeinem Grund verschiedene Varianten in einem Container haben müsste, würde ich diese Lösung sicherlich in Erwägung ziehen. Ich würde auch denken, wie viel schlechter / besser wäre es, die Besucher tatsächlich in eine andere Variante zu stecken. Das Schöne an der Verwendung der Vererbung ist, dass sie post-factum erweiterbar ist: Sie können immer von einer Klasse erben, aber sobald eine Variante festgelegt ist, können Sie sie nicht ändern, ohne den vorhandenen Code tatsächlich zu berühren.
Tags und Links c++ boost templates boost-variant variant