Objekte von Class Template in Container?



  • Davon abgesehen daß doubles keine integralen Werte sind ... was hat das jetzt mit der ursprünglitschen Frage zu tun?



  • Das ist für mich wieder so ein klassischer Fall, wo Du lieber erklären solltest, was Du zu erreichen versuchst. Wenn Du mit deinem Ansatz Values verschiedener Typen im selben Container willst, müsstest Du eine abstrakte Basisklasse erstellen, und Zeiger darauf im Container speichern. Davon würde ich allerdings abraten:

    // Pseudocode, kompiliert evtl. nicht.
    struct BaseValue {
        virtual void printValue() const = 0;
    };
    
    template<class T>
    struct Value : public BaseValue {
        std::string name;
        T value;
        virtual void printValue() const override {
            std::cout << name << ": " << value << '\n';
        }
    };
    
    std::vector<std::unique_ptr<BaseValue>> v;
    v.emplace_back(std::make_unique<Value<int>>("foo", 5));
    

    Wie gesagt, das ist eine ziemlich schlechte Lösung für so ein Problem IMO. Daher lieber std::variant oder wenn's sein muss std::any. Wenn sich die Anzahl verwendeter Typen begrenzen lässt, dann würde ich std::variant wählen.



  • Ich will an meiner Fehlerbehandlung arbeiten und eine eigene Exceptionklasse schreiben. Um mich nicht zu verschlechtern, will ich alle Bezeichner und Werte ausgeben können, die mit einem Fehler zusammenhängen.

    Dafür will ich im dortigen Konstruktor beliebig viele Werte übergeben können. Dies wollte ich mit einer initializer_list machen, aber wie bekomme ich die Werte dort rein?



  • Was. Willst. Du. Konkret?

    (Nein. Nochmal. Nicht *wie* sondern *was*?)



  • Fehlerbehandlung. Exceptionklasse. Werte im Fehlerfall ausgeben können.
    Urgerüst als billiges Beispiel:

    class Exception
    {
    public:
    
        Exception( const std::string& name ) : error_name( name ) {}
    
        void printErrorName() const
        {
            std::cerr << error_name;
        }
    
    private:
    
        std::string error_name;
    };
    
    void getV( const std::vector<int>& vec, const std::size_t i )
    {
        if ( i >= 0 && i < vec.size() )
        {
            std::cout << vec[ i ];
        }
        else
        {
            throw Exception( "range_error" );
        }
    }
    
    int main()
    {
        std::vector<int> vec = { 1, 2, 3 };
    
        try
        {
            getV( vec, 5 );
        }
        catch( const Exception& e )
        {
            e.printErrorName();
        }
    }
    
    

    Nun möchte ich aber noch vec.size() und i ausgeben können.



  • #include <sstream>
    #include <stdexcept>
    #include <vector>
    #include <iostream>
    
    void getV(std::vector<int> const &vec, std::size_t i)
    {
        if (0 < i && i < vec.size())
        {
            std::cout << vec[i];
        }
        else {
            std::stringstream ss;
            ss << "range error in getV(), vec.size(): " << vec.size() << ", i: " << i;
            throw std::range_error{ ss.str() };
        }
    }
    

    Aber warum muss i größer 0 sein?
    Warum überhaupt getV() und nicht vec.at(), das wirft freiwillig.



  • Schreib- oder Denkfehler.

    Ich dachte, es wäre besser, wenn ich im else-Fall keinen Roman schreiben muss, sondern wie "range_error" alle Werte dem Konstruktor übergebe.



  • @Swordfish sagte in Objekte von Class Template in Container?:

    Warum überhaupt getV() und nicht vec.at(), das wirft freiwillig.

    Weil es ein blödes kompilierbares Minimalbeispiel ist!



  • Mach es einfach nicht komplizierter als es ist.



  • Dann habe ich keine Verbesserung gegenüber meinen std::cerr Ausgaben.



  • Für sowas gibt es Debugger --- Dein Programm stürtzt ab, dann machst Du breakpoints hin und kannst sehen, welchen Wert der Index hat, wie groß der vector ist usw. Was deine ursprüngliche Beschreibung angeht

    will ich alle Bezeichner und Werte ausgeben können, die mit einem Fehler zusammenhängen.

    Dafür will ich im dortigen Konstruktor beliebig viele Werte übergeben können.

    Das klingt wie in diesem Thread: C++ Komfort-Exception

    P.S.: Ich habe das Gefühl, dass deine ursprüngliche Fragestellung überhaupt nichts mit dem eigentlichen Problem zu tun hat... Also wie gesagt am Besten immer direkt beschreiben was Du lösen willst, und nicht wie Dein Lösungsansatz für ein unbekanntes Problem aussieht.



  • @zeropage
    Mir war schon klar was du erreichen wolltest, nämlich beliebige Spezialisierungen deines Templates in ein und den selben Container zu stopfen. Nur das geht halt nicht.

    Wenn du möchtest, kannst du eine gemeinsame, polymorphe Basisklasse machen, von der alle Spezialisierungen deines Templates ableiten. Die kann dann eine virtuelle Funktion haben (oder auch mehrere). Dann kannst du sowas wie einen vector<unique_ptr<Basisklasse>> machen.

    Jetzt sind wir vermutlich wieder genau bei der Antwort die du schon gefunden hast und wo dir irgendwas dran nicht passt.

    Und nu?


    Davon abgesehen: Wieso packst du nicht gleich den ganzen Fehlertext den printErrorXxx() ausgeben soll in die Exception?
    Oder, die "saubere" Lösung (die aber oft Overkill ist): du machst für jeden Fehlertyp eine eigenen, von Exception abgeleitete Klasse. Die kann dann printErrorXxx so implementieren wie sie möchte - vorausgesetzt du machst printErrorXxx virtual.



  • @zeropage sagte in Objekte von Class Template in Container?:

    Dann habe ich keine Verbesserung gegenüber meinen std::cerr Ausgaben.

    Dann nimmst eben ein Variadic Template?

    #include <sstream>
    #include <stdexcept>
    #include <vector>
    #include <iostream>
    
    class my_hyper_cool_range_error
    {
    	std::string msg;
    
    public:
    	template<typename T, typename... Ts>
    	my_hyper_cool_range_error(T value, Ts... values)
    	{
    		std::stringstream ss;
    		ss << value;
    		(ss << ... << values);
    		msg = ss.str();
    	}
    
    	std::string const& what() const { return msg; }
    };
    
    void getV(std::vector<int> const &vec, std::size_t i)
    {
    	if (0 < i && i < vec.size()) {
    		std::cout << vec[i];
    	}
    	else {
    		throw my_hyper_cool_range_error{ "range error in getV(), vec.size(): ", vec.size(), ", i: ", i };
    	}
    }
    
    int main()
    {
    	std::vector<int> vec = { 1, 2, 3 };
    
    	try {
    		getV(vec, 5);
    	}
    	catch (my_hyper_cool_range_error &e) {
    		std::cerr << e.what() << "\n\n";
    	}
    }
    


  • Danke. Wenn ich die Arschloch-Bezeichner überlesen kann, schaue ich es mir mal an. Irgendwann oder so. Ist nicht mehr so wichtig jetzt.



  • @zeropage sagte in Objekte von Class Template in Container?:

    Arschloch-Bezeichner

    ?



  • Hallo Asperger?! Oder was?



  • So abwegig sind die Bezeichner gar nicht 😉



  • @zeropage sagte in Objekte von Class Template in Container?:

    Hallo Asperger?! Oder was?

    Ne, paranoid Schizophren.



  • Da weiß man wieder nicht, wie das gemeint ist!

    Da paranoid schizophren nicht zu Deiner Person passt (gibt ja genug zu lesen hier) kann es nur eine Anspielung auf den TO, also mich sein.

    Wenn es nicht so ist, sind wir wieder beim Thema bekloppt. Bzw Asperga.



  • Wer da bekloppt ist!? Du bekommst hier ein gratis Codebeispiel das tut was du willst und von dir kommen darauf saublöde Meldungen. Wenn ich meinen hyper coolen Range Error my_hyper_cool_range_error nennen will, dann tu ich das eben. Wenn es dir nicht passt dann nenn ihn halt anders, Herrgott nochmal.

    @zeropage sagte in Objekte von Class Template in Container?:

    Da weiß man wieder nicht, wie das gemeint ist!

    Bei deinen Beiträgen weiß man das genausowenig. Oder sogar noch weniger:

    @zeropage sagte in Objekte von Class Template in Container?:

    Hallo Asperger?! Oder was?

    wtf? Und das war deine Antwort auf eine schlichte Nachfrage darüber, was du mit

    @zeropage sagte in Objekte von Class Template in Container?:

    Arschloch-Bezeichner

    gemeint hast, was ich nur als einen persönlichen Angriff deuten habe können.

    @zeropage sagte in Objekte von Class Template in Container?:

    Da paranoid schizophren nicht zu Deiner Person passt (gibt ja genug zu lesen hier) kann es nur eine Anspielung auf den TO, also mich sein.

    Und hör auf dir einzubilden du würdest irgendetwas über meine Persönlichkeit aussagen können nur weil du ein paar Beiträge von mir in einem Forum gelesen hast.

    Nein, ich hab' nicht Asperger. Meine Mutter hat mich testen lassen.


Anmelden zum Antworten