Beliebiger Datentyp in C++



  • Beantworte doch bitte meine Frage. Davon hängt nämlich ab, was man dir empfehlen kann.

    < 💡 >



  • Für sowas gibt es z.B. boost::any.



  • Naja, der Datentyp kann immer gleich sein. Man kann z.B. eine ComboBox haben mit UserDatas vom Typ einer struct Point, und eine andere ComboBox vielleicht mit simplen ints.
    Beispiel:

    Point p1, p2, p3; // 3 Point struct
    
    ComboBox* cb = ...
    cb->addItem("entry 1", p1); // cb enthält nur UserData vom Typ Point
    cb->addItem("entry 2", p2);
    ...
    
    Point p = cb->getItem(1); // UserData von Item 1 holen
    

    Wenn ich das mit Templates machen will, muss doch ComboBox eine Templateklasse werden, sprich ComboBox<Point>, oder?



  • Generiker schrieb:

    Die Klasse ComboBox selber soll ja kein Template sein.

    Warum nicht? Dann kann sich der Nutzer am Ende einen Datentypen aussuchen, den er in der ComboBox speichern will und du kannst saubere Funktionen schreiben. Es können nur nicht verschiedene Datentypen in einer ComboBox gespeichert werden, was aber ok sein sollte, denn der Weg mit dem void * oder boost::any steht dem Nutzer weiterhin offen.



  • Generiker schrieb:

    Wenn ich das mit Templates machen will, muss doch ComboBox eine Templateklasse werden, sprich ComboBox<Point>, oder?

    Richtig. Aber das machst nicht du, das macht der Nutzer.



  • nwp3 schrieb:

    Generiker schrieb:

    Wenn ich das mit Templates machen will, muss doch ComboBox eine Templateklasse werden, sprich ComboBox<Point>, oder?

    Richtig. Aber das machst nicht du, das macht der Nutzer.

    Was soll den mit dem "Item" gemacht werden, nachdem es hinzugefügt wurde?



  • Tachyon schrieb:

    nwp3 schrieb:

    Generiker schrieb:

    Wenn ich das mit Templates machen will, muss doch ComboBox eine Templateklasse werden, sprich ComboBox<Point>, oder?

    Richtig. Aber das machst nicht du, das macht der Nutzer.

    Was soll den mit dem "Item" gemacht werden, nachdem es hinzugefügt wurde?

    Nichts. Die sollen einfach nur gespeichert werden und wenn ein Item ausgewaehlt wurde, wird ein Event ausgeloest, dass dem Callback die UserData zurueckliefert.

    Ja, eine Templateklasse waere moeglich, aber irgendwie finde ich es etwas befremdlich, sowas zu schreiben: ComboBox<Point> p;
    Ich dachte auch schon einfach an void* als UserData Type, dann koennte man einfach machen:

    cb->addItem("foo", new Point(2,3));
    

    Mein Problem ist nur: Wer soll den Speicher loeschen? ComboBox kann es nicht machen, da ja ein delete auf einen void Zeiger nicht funktioniert. boost::any ist interessant, aber wegen der einen Methode moechte ich mir nicht extra boost holen...



  • Ich wuerde einfach Type-Erasure verwenden. boost::any funktioniert nicht, weil du ja irgendwie an eine Darstellung der Daten rankommen musst. Ich bastle da mal eben was.



  • Koennte dann ungefaehr so aussehen:

    struct printable
    {
    	template <typename T>
    	printable(T const* value)
    		: data_(value), to_string_impl_(&printable::to_string_impl<T>)
    	{}
    
    	std::string to_string() const
    	{
    		return to_string_impl_(data_);
    	}
    
    private:
    	void const* data_;
    	std::string (* to_string_impl_) (void const*);
    
    	template <typename T>
    	static std::string to_string_impl(void const* data)
    	{
    		std::ostringstream oss;
    		oss << *static_cast<T const*>(data);
    		return oss.str();
    	}
    };
    

    http://ideone.com/VFfDa8

    Deine addItem-Funktion nimmt dann einfach so ein printable als Parameter. Der Konstruktor nimmt ganz bewusst einen Zeiger, damit hier wirklich nur LValues uebergeben werden koennen und damit intern keine Zeiger auf temporaries entstehen, wenn du ein printable abspeicherst. Damit ein Typ printable ist, muss er einfach operator << ueberladen haben. Du kannst dafuer natuerlich auch eine eigene Funktion bauen, wenn dir operator << nicht gefaellt.



  • Ich würde ein std::function -Objekt als Handler mitgeben, der bei Bedarf die gewünschten User-Daten gebunden hat. Da spart man sich das Gefrickel mit irgendwelchen Formen von Type-Ereasure.



  • Generiker schrieb:

    Wenn ich das mit Templates machen will, muss doch ComboBox eine Templateklasse werden, sprich ComboBox<Point>, oder?

    Obligatorischer Hinweis: ComboBox wäre in diesem Fall keine Templateklasse, sondern eine Klassentemplate (d. h. Klassenvorlage). Insbesondere ist ComboBox selbst dann keine Klasse!



  • Type-Erasure hat mit gefrickel relativ wenig zu tun. Finde das sogar eleganter als std::function, und performanter ist es vermutlich auch.


Anmelden zum Antworten