2016-06-06 23 views
3

Ich arbeite an einem C++ Projekt und versuche herauszufinden, wie man eine "dynamische" Variable erstellen kann.Python-style Variablen in C++

In Python können Variablen mehrere Typen haben:

variable = 0 
variable = "Hello" 

In Java ist dies auch (etwas) erreichbar:

Object o = 0; 
o = "Hello"; 

Von dem, was ich zu C im Zusammenhang finden kann ++, gibt es keine object Typ oder "dynamisches" Objekt bei diesem.

Der Grund, warum ich diese brauchen, ist Ich versuche, ein Objekt, das in einer der folgenden Arten nimmt zu erstellen: int, float, char, string, bool, und mir erlauben, Operationen zu tun, wie zum Beispiel:

object o = 0; // currently an int 
o -= 2.5; // now a float 
o += "Test"; // now a string 

Gibt es eine Standardfunktionalität für diese Art von Variable? Wenn nicht, kann es mit Makros gemacht werden, struct 's, etc.?

Ich habe Dinge wie diese gefunden:

template <typename name> 

aber haben keine Ahnung, wie es zu benutzen.

+2

C++ 17 wird 'std :: any' haben, was genau das ist, was Sie wollen. Jetzt können Sie 'boost :: any' verwenden oder Ihre eigene Implementierung ausführen.Dies ist jedoch nicht dynamisch. – user2296177

+0

@ user2296177 Ich arbeite mit C++ 11 und hoffe (aber ich bin glücklich, den Support fallen zu lassen, wenn es nicht möglich ist), Abwärtskompatibilität zu haben. Ich bin nutzlos mit C++, kannst du mir bitte ein Beispiel geben? Ich habe keine Ahnung, wo ich anfangen soll ... – finnrayment

+0

Sie können immer eine Klasse erstellen, die Vektoren aller Typen enthält, die Sie unterstützen möchten, und dann eine Schnittstelle hinzufügen. Aber das scheint auf den ersten Blick eine sehr schlechte Idee in Bezug auf Wartbarkeit und Lesbarkeit zu sein. Ich würde darüber nachdenken, so etwas sehr schwer umzusetzen und eine völlig andere Lösung zu finden. – mirosval

Antwort

7

Sie können die Bibliothek boost.variant verwenden. Grundlegende Gebrauchsanweisungen here. Kurz gesagt, wäre es so etwas wie

using var_t = boost::variant<bool,int,double,string, boost::blank_t>; 
var_t var = "hello"; 
std::cout << boost::get<std::string>(var) << '\n'; 
std::cout << var << '\n'; // if all possible stored types are streamable 

Etwas nicht gerade Teil ist Zugriff auf Wert, ohne den genauen Typ zu kennen. Dies erfordert static visitor. Wenn Sie sich fragen, was der Unterschied zwischen any und variant ist - Sie sind nicht allein, und here is the comparison chart.

+0

Können Sie bitte ausarbeiten? Ich weiß nicht, wie ich diese Dinge implementieren soll, die aus einem ganzen Java/Python-Hintergrund kommen. – finnrayment

+1

Ich weiß nichts, aber das könnte helfen, wenn Sie nicht mit C++ vertraut sind: http://www.boost.org/doc/libs/1_61_0/doc/html/variant.html. Was Sie über Vorlagen gefunden haben, ist nicht das, wonach Sie suchen. –

+0

: O Boost ist plattformabhängig! – finnrayment

3

Jede Sprache hat ihre eigenen idiomatischen Konstrukte, und Sie sollten nicht versuchen, Python-Code in C++ nachzuahmen. Wie von @ user2296177 angegeben, ist das nächste C++ - Tool (in der aktuellen Version) boost :: any, das auch in C++ 17 als std :: any enthalten ist.

Aber sogar Boost: Jede hat einige Einschränkungen: Typen, die einem boost :: any zugewiesen werden, müssen copy constructibles sein, und ihr Destruktor darf niemals Ausnahmen auslösen.

Wenn Sie nur eine bekannte Liste von Typen akzeptieren müssen, können Sie gute alte (aus C stammende) Verbindungen oder deren Boost-automatische äquivalente Boost :: Variante verwenden.

Aber in der Tat sollten Sie sich fragen, warum Sie das brauchen, wie Sie den tatsächlichen Typ verfolgen wollen, ob Sie Casting oder Aliasing erlauben müssen. Da C++ neben den dynamischen Python-Variablen auch die Konvertierung oder das Aliasing zwischen Typen ermöglicht.

TL/DR: Versuchen Sie nicht, ein Python-Idiom zu imitieren und genau zu analysieren, was Sie wirklich brauchen. Eine Union könnte die Werkzeuge in einigen Anwendungsfällen sein, ein Leerer-Zeiger in einigen anderen oder eine dedizierte Struktur könnte notwendig sein. Es kommt wirklich auf den realen Anwendungsfall an.

+0

Das Problem, das ich habe, ist, dass ich potentiell ** irgendeine ** Art von Objekt ** nehme. Ich entwerfe das Programm so, dass ** ich ** den Typ überhaupt nicht verfolgen kann, sondern Operationen direkt auf die Variable anwende und Ergebnisse auf Anfrage drucke. – finnrayment

+0

@Serge - AST-Parsing ist ein gültiger Anwendungsfall für 'variant' /' any' in C++, parsen manchmal auch Tagtyp-Wert-Protokolle. Was auch immer in billiger/lesbar/schnell (egal welcher Priorität) Code ist eine gute Lösung, egal was die Sprache ist, IMHO. – bobah

+0

@frayment: Was sind die Operationen, die allen Typen gemeinsam sind, die Sie verarbeiten möchten? Und möchten Sie nur benutzerdefinierte Typen (könnte von einer einzigen Schnittstelle ableiten) oder auch Standardtypen (String, Liste, Karte) oder sogar intrinsics (int, float, char)? Und ist die Liste der erlaubten Typen begrenzt oder nicht? –