Objekte von Class Template in Container?



  • #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.



  • @zeropage Ich glaube Du hast das evtl. falsch interpretiert, ich denke nicht, dass die Bennenung der Klasse abweisend gemeint war. Das kostet ja auch Zeit, so ein nettes Beispiel zu erstellen.

    std::stringstream ss;
    ss << value;
    (ss << ... << values);
    msg = ss.str();
    

    Ich frage mich, wie man auf diese magischen Methoden kommt, um Parameterlisten zu entpacken...
    Cool, dass das so geht, ich hätte immer zwei Funktionen gebraucht, wobei eine immer als erstes Argument den std::ostream nimmt, und dann eben rekursiv arbeitet.

    In der Praxis würde man besser von std::exception oder std::runtime_error vererben, oder?



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

    Weil es ein blödes kompilierbares Minimalbeispiel ist!

    Tjoa. Ist es nicht. Ein compilierbares Minimalbeispiel ist etwas das man so wie es ist durch einen Compiler jagen kann.

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

    Das kostet ja auch Zeit, so ein nettes Beispiel zu erstellen.

    Ja. Und deshalb nerven mich solche Reaktionen wie ...

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

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

    ... die von völliger Ignoranz, Undankbarkeit zeugen.

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

    Ich frage mich, wie man auf diese magischen Methoden kommt, um Parameterlisten zu entpacken...

    Ich habe nach "fold expression c++" gegoogelt, das erste Ergebnis angeklickt, die Beispiele angesehen. Dann hab ich's hingeschrieben. Find' ich auch nicht abwegig, wenn man partout nicht d'rauf kommt wie es geht und es nach ein paar Versuchen satt hat von seinem Compiler beschimpft zu werden. Machen andere das anders?

    Aber es geht eloganter:

    #include <string>
    #include <sstream>
    
    class my_hyper_cool_range_error
    {
    	std::string msg;
    
    public:
    	template<typename... Ts>
    	my_hyper_cool_range_error(Ts... values)
    	: msg{ (std::ostringstream{} << ... << values).str() }
    	{}
    
    	std::string const& what() const { return msg; }
    };
    

    zumindest ... ich glaube es sollte so gehen, oder irre ich mich? Ich weiß eben nicht, ob es standartkonform ist. cl mag es, clang und gcc mögen es nicht. Hab' aber auch keine Idee, woher die beiden letzten sich aus einem std::ostringstream einen std::basic_ostream<char> herdichten. *schulterzuck*

    @Columbo, @Camper, @rapso, @Bashar ... any light on that? // edit @SeppJ Du darfst natürlich auch gerne mitmachen 😜

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

    In der Praxis würde man besser von std::exception oder std::runtime_error vererben, oder?

    Vermutlich.


  • Mod

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

    (std::ostringstream{} << ... << values).str()

    operator<< gibt ostream& zurueck. Es gab ein LWG Proposal um einen entsprechenden overload bereitzustellen, aber scheinbar ist daraus nichts geworden. Ergo

    static_cast<std::ostringstream&>((std::ostringstream{} << ... << values)).str()
    


  • @Columbo Oh, ok. Danke. Hast Du zufällig einen Link zu dem Proposal rumliegen?

    Dann das komplette Beißspiel auf Basis von @zeropage s Beispiel:

    #include <sstream>
    #include <stdexcept>
    #include <vector>
    #include <iostream>
    
    class my_hyper_cool_range_error
    {
    	std::string msg;
    
    public:
    	template<typename... Ts>
    	my_hyper_cool_range_error(Ts... values)
    	: msg{ static_cast<std::ostringstream&>((std::ostringstream{} << ... << values)).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()
    {
    	my_hyper_cool_range_error foo{ 3 };
    	std::cout << foo.what() << '\n';
    	std::vector<int> vec = { 1, 2, 3 };
    
    	try {
    		getV(vec, 5);
    	}
    	catch (my_hyper_cool_range_error &e) {
    		std::cerr << e.what() << "\n\n";
    	}
    }
    

  • Mod

    Noch ein kleiner Spass:

    #include <sstream>
    #include <iostream>
    #include <string>
    #include <cassert>
    
    template <typename String = std::string>
    class append_buf : public std::basic_streambuf<typename String::value_type> {
        String* str;
        static constexpr double resize_factor = 1.5;
    
    public:
        using Base = std::basic_streambuf<typename String::value_type>;
        using typename Base::char_type;
        using typename Base::int_type;
        using typename Base::traits_type;
    
        append_buf(String* s) : str(s) {
            assert(str);
            Base::setp(str->data(), str->data() + str->size());
        }
    
        int_type overflow(int_type ch) {
            if (traits_type::eq_int_type(ch, traits_type::eof()))
                return traits_type::eof();
            auto old_size = str->size();
            str->resize(resize_factor * (str->size() + 1));
            Base::setp(str->data() + old_size, str->data() + str->size());
            return Base::sputc((char_type)ch);
        }
    };
    
    int main() 
    {
        std::string s;
        append_buf buf(&s);
        std::ostream stream(&buf);
        stream << 234 << "awefa";
    
        std::cout << "string: " << s; 
    }
    

    Aber dann kann man natuerlich msg nicht mehr elegant in der Initialisierungsliste initialisieren. Hmmm..


Anmelden zum Antworten