Funktion, die einen unbekannten Typ zurückgibt

7
%Vor%

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.

    
Jacob 31.08.2009, 17:22
quelle

13 Antworten

24

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:)

%Vor%

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.

    
AraK 31.08.2009, 17:25
quelle
8

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.

    
anon 31.08.2009 17:26
quelle
5

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%     
Kirill V. Lyadvinsky 31.08.2009 19:14
quelle
3

Verwenden Sie boost :: any :

%Vor%     
Cătălin Pitiș 31.08.2009 17:27
quelle
3

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 ++.

    
Nathan Kitchen 31.08.2009 17:36
quelle
3

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:

%Vor%

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>     

Agnel Kurian 31.08.2009 17:35
quelle
3
  

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"?

  • Eine Lösung, die sauber nur mit ANSI (oder ISO) C ++ kompiliert? Wenn dies der Fall ist, ist Boost die ANSI C ++ - Lösung
  • Eine Lösung bereits in der ANSI C ++ - Standardbibliothek implementiert? Wenn ja, dann gibt es keine solche Lösung (und es gibt keinen "Beweis", außer "lies den Sprachstandard durch und sieh, ob du eine solche Klasse finden kannst. Wenn du nicht kannst, ist es nicht da").
  • Eine Lösung, die Sie selbst mit nur ANSI C ++ implementieren können. Dann lautet die Antwort "Ja, du könntest den Quellcode von Boost kopieren".

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.

    
jalf 31.08.2009 18:46
quelle
1

Sie könnten eine Union verwenden:

%Vor%     
Marc 31.08.2009 17:33
quelle
0

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.)

    
fbrereto 31.08.2009 17:37
quelle
0

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.

    
count0 31.08.2009 18:14
quelle
-1

Wenn der Benutzer weiß, was eingegeben wurde, können Sie eine Vorlage verwenden, um dies zu beheben. Wenn nicht, kann ich mir keine Lösung vorstellen.

    
martiert 31.08.2009 17:24
quelle
-1

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.

    
Broken_Window 31.08.2009 18:28
quelle
-3

SOMETHING = void *

Sie müssen den zurückgegebenen Wert umwandeln, damit Sie wissen, was zurückgegeben wird.

%Vor%     
Jay 31.08.2009 17:36
quelle

Tags und Links