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:


Anmelden zum Antworten