Nun, da ich a = 1 impliziert, dass ich eine ganze Zahl usw. zurückgeben muss, gibt es trotzdem eine Rückgabe von Doit () an eine Variable mit variablem Datentyp?
Im Wesentlichen, mit was ersetze ich ETWAS ?
PS: Ich versuche eine Alternative zu finden, um eine Struktur / Union zurückzugeben, die diese Datentypen enthält.
Sie können boost::any
oder boost::variant
um zu tun, was Sie wollen. Ich empfehle boost::variant
, weil Sie die Sammlung von Typen kennen, die Sie zurückgeben möchten.
Dies ist ein sehr einfaches Beispiel, obwohl Sie mit variant
noch viel mehr erreichen können. Überprüfen Sie die Referenz für weitere Beispiele:)
Die Ausgabe:
%Vor% Ich würde boost::variant
anstelle von union
verwenden, weil Sie keine Nicht-POD-Typen innerhalb von union
verwenden können. Außerdem ist boost::any
großartig, wenn Sie den Typ, mit dem Sie es zu tun haben, nicht kennen. Ansonsten würde ich boost::variant
verwenden, weil es viel effizienter und sicherer ist.
Beantworten der bearbeiteten Frage: Wenn Sie Boost
nicht mit Ihrem Code versenden möchten, werfen Sie einen Blick auf bcp
. Die Beschreibung von bcp
von demselben Link:
Das Dienstprogramm bcp ist ein Werkzeug für Teilmengen von Boost zu extrahieren, ist es nützlich für Boost-Autoren, die das wollen Verteilen Sie ihre Bibliothek separat von Boost, und für Boost Benutzer, die möchte eine Teilmenge von Boost verteilen mit ihrer Anwendung.
bcp kann auch darüber berichten, welche Teile von Steigern Sie Ihren Code ist abhängig, und Welche Lizenzen werden von diesen verwendet? Abhängigkeiten.
C ++ ist eine stark typisierte Sprache und hat kein Konzept eines unbekannten Typs. Du könntest versuchen, boost :: any zu benutzen, was (irgendwie) jeden Typ spezifizieren kann. Ich würde jedoch das Design Ihrer Funktion in Frage stellen.
Wenn Sie den Typ zum Zeitpunkt der Kompilierung kennen, können Sie Vorlagen verwenden. Wenn der Typ von der Laufzeit abhängt, ist die Verwendung von Vorlagen keine Option.
%Vor%Der übliche Weg, um so etwas zu erreichen, ist C, das nicht immer in C ++ funktioniert, mit einem union- und einem type-Feld:
%Vor%Dies funktioniert in C ++ nicht, wenn einer der möglichen Wertetypen eine Klasse mit einem nicht-trivialen Konstruktor ist, weil es nicht immer klar ist, welcher Konstruktor aufgerufen werden sollte. Boost.Variant verwendet eine komplexere Version dieses Ansatzes, um diese Art zu bieten Konstruieren Sie für alle Werttypen in C ++.
Sie könnten eine Struktur verwenden, die einen void*
enthält, der auf den Wert verweist, der zusammen mit einem size_t
zurückgegeben werden soll, der die Größe des zurückgegebenen Objekts angibt. Etwas wie das:
Denken Sie daran, dass void*
auf einen Wert im Heap zeigen sollte (d. h. dynamisch zugewiesen mit new
oder malloc
) und der Aufrufer sollte darauf achten, das zugewiesene Objekt freizugeben.
Nachdem ich das gesagt habe, denke ich, dass es insgesamt eine schlechte Idee ist.
Bearbeiten: Sie sollten auch überlegen, ein Flag einzufügen, das angibt, was in der obigen Struktur zurückgegeben wurde, damit der Aufrufer einen Sinn daraus ableiten kann, sofern der Aufrufer nicht weiß, welchen Typ er erwartet. p>
EDIT: boost :: any mit bcp (danke AraK) scheint die beste Lösung zu sein, aber ist es möglich (bis zu einem gewissen Grad) zu beweisen, dass es keine ANSI C ++ Lösung für dieses Problem gibt?
Sie scheinen ein bisschen verwirrt über die Terminologie hier.
Nennen wir es zunächst ISO C ++, sollen wir? Es wurde 1998 von der ISO standardisiert und seitdem haben sich die Leute darauf bezogen, wenn es um "Standard-C ++" geht. Nun, was meinst du mit einer "ANSI C ++ Lösung"?
Ich kann mir nicht vorstellen, welche Art von "Beweis" Sie suchen würden. C ++ ist ein Dokument in Prosaform. Es ist keine mathematische Gleichung. Es kann nicht "bewiesen" werden, außer indem man sagt "lies den Standard". Der Nachweis, dass etwas in der Sprache oder in der Standardbibliothek definiert ist, ist einfach - weisen Sie einfach darauf hin, wo im Standard es beschrieben wird. Aber zu beweisen, dass etwas nicht ist, ist im Grunde unmöglich - außer durch Aufzählung jedes einzelnen Satzes des Standards und Dokument, dass keines von ihnen beschreibt, wonach Sie suchen . Und ich bezweifle, dass du irgendjemanden finden wirst, der das für dich tun will.
Wie auch immer, die korrekte C ++ - Standardlösung ist , um Boost zu verwenden. Es ist keine schwergewichtige Lösung. Boost ist relativ leicht, da Sie genau die benötigten Bits einfügen können, ohne dass Abhängigkeiten vom Rest der Bibliothekssammlung bestehen.
Nach dem, was Sie beschrieben haben (eine leichte Anwendung für eine breite Benutzerbasis), gibt es keinen Grund, Boost nicht zu verwenden. Es kann Ihren Code vereinfachen und die Anzahl der Fehler verringern, die durch das neue Rad verursacht werden. Beim Verteilen der kompilierten ausführbaren Datei fallen keine Kosten an. Die Boost.Any
-Bibliothek ist, wie ein Großteil von Boost, nur header-only und wird einfach in Ihre ausführbare Datei kompiliert. Es müssen keine separaten Bibliotheken verteilt werden.
Es kann nichts gewonnen werden, wenn man versucht, das Rad neu zu erfinden. Ihre ausführbare Datei wird nicht kleiner oder effizienter sein, aber wird mehr fehlerhaft sein.
Und ich wette, dass Ihre selbstgebraute Lösung nicht ANSI C ++ sein wird. Es wird auf irgendeine Form von undefiniertem Verhalten angewiesen sein. Wenn Sie eine ANSI-C ++ Lösung wünschen, ist Boost Ihre beste Wahl.
Die Adobe Source Libraries verfügen auch über adobe::any_regular_t
, mit dem Sie jeden Typ speichern können, solange er das Modell erstellt Regelmäßiges Konzept. Sie würden Ihren Rückgabewert ähnlich wie mit boost::any
umhüllen. (Auf der verlinkten Seite gibt es auch eine Dokumentation dazu, wie sich adobe::any_regular_t
von boost::any
unterscheidet - natürlich sollte der Typ, den Sie auswählen, von den Anforderungen Ihres Codes abhängen.)
Sie könnten stattdessen durch Verweis übergeben und typesave und überprüfen, ob es zur gleichen Zeit funktionierte, würde auch keine zusätzliche Bibliothek beinhalten (Ihre Art von C ++ - Lösung):
%Vor%...
Ich finde diese Lösung in puncto Design oft sauberer. Es ist bedauerlich, dass Funktionssignaturen nicht mehrere Typen als Rückgabetypen zulassen, aber auf diese Weise können Sie alles weitergeben.
Ich denke, das Problem besteht in diesem Funktionsdesign. Hast du versucht, zu überladen?
%Vor%Innerhalb von DoIt-Funktionen können Sie mehr Code platzieren und sie dazu bringen, andere Funktionen aufzurufen, um Code nicht zu wiederholen.
Tags und Links c++ variant visual-c++-2005