boost::variant - immer erreichbare Instanzen der Template-argumente
-
Hohoho! :xmas2:
Hab endlich Boost 1.48 gebaut und mich gleich auf dieses Tutorial begeben.
Da hab ich boost::variant gefunden. Dieser Code compiliert und funktioniert einwandfrei:
#include <boost/variant.hpp> #include <iostream> int main() { boost::variant<std::string, int> a; a = std::string("hellao"); std::cout << boost::get<std::string>(a) << '\n'; a = 5; std::cout << boost::get<int>(a) << '\n'; }Dieser (so leid es mir tut) nicht:
#include <boost/variant.hpp> #include <iostream> int main() { boost::variant<std::string, int> a; a = std::string("hellao"); a = 5; std::cout << boost::get<std::string>(a) << '\n'; std::cout << boost::get<int>(a) << '\n'; }Versteht jemand, was ich meine? Ich will, dass die Klasse für jeden Datentyp (den ich als Template-Parameter übergeben hab) eine immer erreichbare Instanz anlegt. Das tut er anscheinend nicht, was aber jetzt genau? Könnt's mir vielleicht jemand erklären?
THX (& im V*r**s)
-
Eine variant ist im Prinzip eine union ohne deren Probleme. Du suchst nicht etwa std::tuple?
-
314159265358979 schrieb:
Eine variant ist im Prinzip eine union ohne deren Probleme. Du suchst nicht etwa std::tuple?
Seh ich mir gleich an, thx
Edit: jup, das war's
-
Ich hoffe, ich habe Aufgabe 1 richtig gelöst:
Definieren Sie einen Datentyp configuration, der Name-Wert-Paare speichern kann. Namen sind dabei vom Typ std::string, Werte vom Typ std::string, int oder float. Speichern Sie dann in der Funktion main() folgende Name-Wert-Paare in einem Objekt vom Typ configuration: path=C:\Windows, version=3 und pi=3.1415. Geben Sie dann die Name-Wert-Paare zum Test auf die Standardausgabe aus.
#include <boost/variant.hpp> #include <iostream> #include <string> #include <utility> using std::string; using std::ostream; class configuration { std::pair<string, boost::variant<string, int, float>> values; public: configuration() = delete; configuration(const string& key, int value) : values(std::make_pair(key, value)) {} configuration(const string& key, float value) : values(std::make_pair(key, value)) {} configuration(const string& key, const string& value) : values(std::make_pair(key, value)) {} friend ostream& operator<<(ostream&, const configuration&); }; ostream& operator<<(ostream& os, const configuration& c) { return os << c.values.first << " = " << c.values.second; } int main() { std::cout << configuration ("path", "C:\\Windows") << '\n' << configuration ("pi", 3.1415f) << '\n' << configuration ("version", 3) << '\n'; }Edit: und Aufgabe 2:
Erweitern Sie Ihre Lösung zu Aufgabe 1 dahingehend, dass nach der Ausgabe der Name-Wert-Paare path auf den neuen Wert C:\Windows\System gesetzt wird. Geben Sie anschließend zum Test den neuen Wert von path auf die Standardausgabe aus.
#include <boost/variant.hpp> #include <iostream> #include <string> #include <utility> using std::string; using std::ostream; class configuration { std::pair<string, boost::variant<string, int, float>> values; public: configuration() = delete; configuration(const string& key, int value) : values(std::make_pair(key, value)) {} configuration(const string& key, float value) : values(std::make_pair(key, value)) {} configuration(const string& key, const string& value) : values(std::make_pair(key, value)) {} friend ostream& operator<<(ostream&, const configuration&); void set_value(const boost::variant<string, int, float>& var) { values.second = var; } void get_value(const boost::variant<string, int, float>& var) const { return boost::get< } }; ostream& operator<<(ostream& os, const configuration& c) { return os << c.values.first << " = " << c.values.second; } int main() { configuration path("path", "C:\\Windows"); std::cout << path << '\n'; path.set_value("C:\\Windows\\system"); std::cout << path << '\n'; }
-
Definieren Sie einen Datentyp configuration, der Name-Wert-Paare speichern kann. Namen sind dabei vom Typ std::string, Werte vom Typ std::string, int oder float. Speichern Sie dann in der Funktion main() folgende Name-Wert-Paare in einem Objekt vom Typ configuration: path=C:\Windows, version=3 und pi=3.1415. Geben Sie dann die Name-Wert-Paare zum Test auf die Standardausgabe aus.
template<typename T> struct configuration { T value; std::string name; configuration(const std::string& name, const T& value) : name(name), value(value) {} }; #include <iostream> std::ostream& operator<< (std::ostream& s, const configuration& config) { s << config.name << " = " << config.value; return s; } #include <string> int main() { configuration<float> pi("pi", 3.1415); configuration<int> version("version", 3); configuration<std::string> path("path", "C:/windows"); std::cout << pi << '\n' << version << '\n' << path << std::endl; }Erweitern Sie Ihre Lösung zu Aufgabe 1 dahingehend, dass nach der Ausgabe der Name-Wert-Paare path auf den neuen Wert C:\Windows\System gesetzt wird. Geben Sie anschließend zum Test den neuen Wert von path auf die Standardausgabe aus.
int main() { configuration<float> pi("pi", 3.1415); configuration<int> version("version", 3); configuration<std::string> path("path", "C:/windows"); std::cout << pi << '\n' << version << '\n' << path << std::endl; path.value = "C:/Windows/System"; std::cout << path << std::endl; }bb
-
Definieren Sie einen Datentyp configuration, der Name-Wert-Paare speichern kann.
Das klingt für mich so, als solle der Detentyp mehrere Paare abspeichern können. Macht für eine Konfiguration ja auch mehr Sinn.
typedef std::map<std::string, boost::variant<std::string, int, float>> configuration;
-
unskilled schrieb:
...
Keine Datenkapselung, unnötige Templates. Hier wirst du noch was werfen müssen wenn feststeht dass auch wirklich nur floats, int und strings als Paarwert verwendet werden dürfen... :xmas1: