Datentyp zur Leufzeit festlegen



  • freak4fun schrieb:

    Moin,
    ich möchte den Benutzer einen Datentyp festlegen lassen. Er soll von einer Auswahl (Combobox) vorgegebener Typen (String, int, double) wählen können. Wie mache ich das? 😕

    python nehmen



  • Im entferntesten kannst du so etwas mit Laufzeitpolymorphie erreichen. Sinvoller wird es dadurch aber auch nicht.



  • Müsste mit einer

    union foo {
            std::string str;
            int i;
            double d;
    }
    

    oder wilder

    reinterpret_cast<type>
    

    klappen, aber das beste wäre wohl das Design zu über denken.



  • Einfacher Vorschlag:
    Packe alles, was der Benutzer machen soll in einzelne Funktionen, die sich nach dem Datentyp unterscheiden. Also FunctionInt, FunctionDouble, FunctionString, etc. Dann lasse - wie gewünscht - den Benutzer in der Combobox auswählen. Alternativ kannst du auch mit Funktionsüberlagerung auskommen - erscheint mir aber etwas aufwendiger.



  • irgendwer schrieb:

    Müsste mit einer

    union foo {
            std::string str;
            int i;
            double d;
    }
    

    Naja... Zu dem Design brauch man wohl nix sagen...

    irgendwer schrieb:

    oder wilder

    reinterpret_cast<type>
    

    Ui...
    wilder?
    Allerdings...
    Sag mir einen Compiler oder Betriebssystem, wo das funktioniert.
    Das funktioniert weder von int nach double oder umgekehrt, geschweige denn mit std::string

    EDIT: Funktioniert heißt nicht nur kompiliert 😉



  • Naja. Man könnte das natürlich auch umgehen und das ganze mit Zeigern machen. Wird wegen dem aber nicht besser.

    Besseres Design ist hier wahrscheinlich die beste Lösung.



  • drakon schrieb:

    Besseres Design ist hier wahrscheinlich die beste Lösung.

    Eine genauere Problemspezifikation wäre der erste Schritt 🙄



  • CSpille schrieb:

    drakon schrieb:

    Besseres Design ist hier wahrscheinlich die beste Lösung.

    Eine genauere Problemspezifikation wäre der erste Schritt 🙄

    Nein. Es macht keinen Sinn, dass er sein Problem beschreibt, wozu er offensichtlich den falschen Weg wählt. Wenn er nochmal über das Design nachdenkt, dann wird er wahrscheinlich selbst auf eine bessere Lösung kommen.



  • drakon schrieb:

    Naja. Man könnte das natürlich auch umgehen und das ganze mit Zeigern machen. Wird wegen dem aber nicht besser.

    War dieser Kommentar auf den reinterpreter_cast bezogen?

    Dafür würde dann aber auch ein static_cast reichen:

    #include <iostream>
    #include <string>
    
    int main(int argc, char** argv)
    {
            void* v;
            int i = 123;
            v = &i;
            std::cout <<  *static_cast<int*>(v) << std::endl;
            double d = 1.23;
            v = &d;
            std::cout <<  *static_cast<double*>(v) << std::endl;
            std::string s("1,23");
            v = &s;
            std::cout <<  *static_cast<std::string*>(v) << std::endl;
            return 0;
    }
    


  • drakon schrieb:

    CSpille schrieb:

    drakon schrieb:

    Besseres Design ist hier wahrscheinlich die beste Lösung.

    Eine genauere Problemspezifikation wäre der erste Schritt 🙄

    Nein. Es macht keinen Sinn, dass er sein Problem beschreibt, wozu er offensichtlich den falschen Weg wählt. Wenn er nochmal über das Design nachdenkt, dann wird er wahrscheinlich selbst auf eine bessere Lösung kommen.

    Ich denke hier gibt es zwei verschiedene Ebenen der Problemspezifikation.
    Eine für die Benutzeranforderungen und eine auf C++-Ebene.
    Ich meinte dabei die Benutzeranforderungen.



  • CSpille schrieb:

    Ich denke hier gibt es zwei verschiedene Ebenen der Problemspezifikation.
    Eine für die Benutzeranforderungen und eine auf C++-Ebene.
    Ich meinte dabei die Benutzeranforderungen.

    Sehe ich auch so. Imho ist es in den seltesten Fällen sinnvoll den Benutzer mit Typisierung zu quälen, es sei den das ist Teil der Problemstellung.



  • Einigen wir uns darauf, dass sowohl union , reinterpret_cast als auch static_cast ungeeignet (wenn nicht unmöglich) sind und warten, bis freak4fun sich genau ausdrückt?



  • Nexus schrieb:

    Einigen wir uns darauf, dass sowohl union , reinterpret_cast als auch static_cast ungeeignet (wenn nicht unmöglich) sind und warten, bis freak4fun sich genau ausdrückt?

    Ja, das klingt gut. 🙂

    Es geht um folgendes: Ich möchte csv-Dateien importieren deren Aufbau ich nicht kenne. Der Benutzer soll nun wählen können, ob es sich bei einer Spalte um eine Zeichenkette, eine Ganzzahl oder eine Kommazahl handelt.
    Ja, ich traue diese Auswahl zu. 😉

    Ich bin prinzipiell für jede Idee dankbar. Gern auch eine Lösung um den benutzer die Entscheidung abzunehmen. 😃

    Ich find es riesig wie sehr ihr euch hier bemüht, vielen Danke! 💡



  • da csv text ist und bleibt, würde ich das auch so belassen.
    Einfach Eingabe/Ausgabe entsprechend "Filtern";

    int ValueType;
    std::string csvValue;
    switch(ValueType)
    {
       case 0:     // Hier Int einlesen
          csvValue = // int to string  
          break;
       case 1:     // Hier float einlesen
          csvValue = // float to string  
          break;
       case 3:     // Hier string einlesen
          csvValue = // string 
          break;
    
    }
    

    oder halt über laufzeit polymorphie

    class Basis
    {
       public:
       virtual std::string GetValue() = 0;
       virtual void SetValue(std::string text) = 0;
    };
    class IntKlasse : public Basis
    {
       int Value
       public:
       virtual std::string GetValue();
       virtual void SetValue(std::string text);
    
    }
    class FloatKlasse : public Basis
    {
       float Value
       public:
       virtual std::string GetValue();
       virtual void SetValue(std::string text);
    
    }
    usw..
    


  • freak4fun schrieb:

    Es geht um folgendes: Ich möchte csv-Dateien importieren deren Aufbau ich nicht kenne.

    Was willst du nach dem Importieren mit den Daten machen?



  • @BigNeal: Danke, das sieht sehr interessant aus. Das schau ich mir mal an. 😉

    @CSpille: Duchschnitte berechnen mit den Double/int, Strings zB als Anzeigenamen. Die CSV-Dateien werden dann als eine Datei zusammengefasst. 👍



  • @ BigNeal:

    #include <string>
    #include <sstream>
    #include <iostream>
    
    class Type
    {
    	protected:
    		std::stringstream myStream;
    
    	public:
    		std::string getValue() const { return myStream.str(); }
    };
    
    class TypeString : public Type
    {
    	public:
    		TypeString(const std::string& s) 
    		{
    			myStream << s;
    		}
    };
    
    class TypeInt : public Type
    {
    	public:
    		TypeInt(int i) 
    		{
    			myStream << i;
    		}
    };
    
    class TypeFloat : public Type
    {
    	public:
    		TypeFloat(float f) 
    		{
    			myStream << f;
    		}
    };
    
    int main()
    {
    	TypeInt i(10);
    	TypeFloat f(10.5);
    	TypeString s("Test");
    
    	std::cout << i.getValue() << std::endl;
    	std::cout << f.getValue() << std::endl;
    	std::cout << s.getValue() << std::endl;
    }
    

    Aber wo soll der Sinn sein? Mit einem std::string kann man nicht rechnen!



  • Jetzt hab ich etwas zusammengefrickelt bekommen 😃

    #include <string>
    #include <sstream>
    #include <iostream>
    #include <ctime>
    
    #define DECLARE_NEW_TYPE(RealType, TypeName) class TypeName : public Type { public: TypeName(RealType a) { myStream << a; myType = #TypeName; } };
    
    class Type
    {
    	protected:
    		std::stringstream myStream;
    		std::string myType;
    
    	public:
    		template <typename T>
    		T getValue() 
    		{ 
    			T tmp; 
    			myStream >> tmp; 
    			return tmp; 
    		}
    
    		const std::string& getType() const { return myType; }
    };
    
    DECLARE_NEW_TYPE(int, TypeInt)
    DECLARE_NEW_TYPE(float, TypeFloat)
    DECLARE_NEW_TYPE(std::string, TypeString)
    
    int main()
    {
    	TypeInt i(10);
    	TypeFloat f(10.5);
    	TypeString s("lol");
    
    	std::cout << i.getValue<int>() << ", " << i.getType() << std::endl;
    	std::cout << f.getValue<float>() << ", " << f.getType() << std::endl;
    	std::cout << s.getValue<std::string>() << ", " << s.getType() << std::endl;
    }
    

    Lässt sich leicht erweitern und der Typ kann auch mit getType zur Laufzeit ermittelt werden. und mit getValue<Typ> abgefragt werden.



  • Oha, das kann ja was werden. Da werd ich mich dan mal am WE ran setzen. Danke dir für deine Mühe, jkljkl ( sehr kreativer nick ^^). 😉



  • jkljkl ist der Bruder von asdasd 😉


Anmelden zum Antworten