Welche Typen sind erlaubt?



  • Abend,

    Ich habe ein Klassentemplate und in einer Methode habe ich diese Zeile:

    T entrySum = static_cast<T>(0);
    

    Natürlich kann T jetzt jeder primitiver Typ wie float, int etc. sein. Aber könnte T nun auch eine Klasse wie complex sein?


  • Administrator

    Jeglicher Typ wird aktzeptiert, welcher einen Konstruktor hat, welcher eine 0 entgegen nehmen kann. Also auch std::complex sofern der übergebene Typ an std::complex einen impliziten Konstruktor hat, welcher eine 0 aktzeptieren kann.

    Grüssli 🙂



  • Dravere schrieb:

    Also auch std::complex sofern der übergebene Typ an std::complex einen impliziten Konstruktor hat, welcher eine 0 aktzeptieren kann.

    Ein expliziter Konstruktor geht auch, es handelt sich hier um eine explizite Typkonvertierung.

    Ich freue mich diesbezüglich auch auf C++0x mit seinen expliziten Konvertierungsoperatoren. Dann ist es endlich möglich, static_cast auch vollständig mit Klassen einzusetzen.



  • Ok, danke. Dann habe ich noch 2 kleine Fragen:

    Die Funktion zum multiplizieren eines Skalars mit einem Vektor sieht bei mir so aus:

    const Vector3<T> operator*(const T& scalar, const Vector<T>3& rhs);
    

    1. Frage: Soll ich das so lassen mit der konstanten Referenz beim scalar, oder sollte ich da einfach ein T scalar draus machen?

    Nur wenn ich jetzt 2 float-Vektoren anlege und mit einem int multipliziere:

    Vector3<float> h1(2, 3, 5);
    Vector3<float> h2(-1, 1, 2);
    
    h2 = 2*h1;
    

    bekomme ich folgenden Fehler:

    error C2679: binary '*' : no operator found which takes a right-hand operand of type 'Vector3<T>' (or there is no acceptable conversion)

    Das verstehe ich nicht. Für den Compiler sollte doch dann da stehen:

    const Vector3<float> operator*(const float& scalar, const Vector<float>3& rhs);
    

    und es sollte locker die 2 in einen const float& gecasted werden können?
    2. Frage: Wieso geht das nicht? Was muss ich machen, damit das geht? 😕


  • Administrator

    Nexus schrieb:

    Dravere schrieb:

    Also auch std::complex sofern der übergebene Typ an std::complex einen impliziten Konstruktor hat, welcher eine 0 aktzeptieren kann.

    Ein expliziter Konstruktor geht auch, es handelt sich hier um eine explizite Typkonvertierung.

    Nein, geht nicht! Probier es selber aus:

    #include <complex>
    
    class Test
    {
    public:
    	Test() { };
    	explicit Test(int) { }
    };
    
    template<typename T>
    void foo()
    {
    	T entry = static_cast<T>(0);
    }
    
    int main()
    {
    	foo<int>();
    	foo<void*>();
    	foo<Test>();
    	foo<std::complex<Test> >(); // Error
    
    	return 0;
    }
    

    @klassa222,
    2 ist nach Standard ein int .
    2.0 ist nach Standard ein double .
    2.0f ist nach Standard ein float .

    Grüssli



  • Äh, es geht also NUR, wenn T einen impliziten Ctor mit einem Parameter hat, richtig?

    @klassa222,
    2 ist nach Standard ein int.
    2.0 ist nach Standard ein double.
    2.0f ist nach Standard ein float

    Ja, das weiß ich. Aber meine 2 Fragen aus meinem letzten Posting beantwortet das irgendwie nicht^^



  • Dravere, sorry, ich bin wohl etwas müde. Ich habe das gemeint:

    class MyClass
    {
        public:
    	    explicit MyClass(int i) {};
    };
    
    int main() 
    { 
    	int i = 5;
    	static_cast<MyClass>(i);
    }
    

  • Administrator

    Mal schauen, ob ich nicht auch schon zu müde bin, aber ich probier es, zu erklären 🙂

    klassa2 schrieb:

    Äh, es geht also NUR, wenn T einen impliziten Ctor mit einem Parameter hat, richtig?

    Nein, bei T ist es egal. Aber wenn du std::complex übergibst, dann muss der std::complex<Type>::value_type einen impliziten Konstruktor haben, welcher eine 0 aktzeptieren kann. Schau mein Beispiel an, welches ich dem Nexus gezeigt habe. Damit sollte es eigentlich klar werden.

    klassa2 schrieb:

    Ja, das weiß ich. Aber meine 2 Fragen aus meinem letzten Posting beantwortet das irgendwie nicht^^

    Ok, Frage 1 ist einfach:
    Lass es bei der Referenz auf ein konstantes Objekt. Falls da mal ein grösseres Objekt übergeben werden sollte, ist die Referenz auf das konstante Objekt definitiv besser.

    Zur Frage 2:
    Bevor die Funktion aufgerufen wird, wird sie vom Kompiler instanziert. Dabei probiert er den richtigen Typen für T zu finden. Du übergibst:
    1. Argument: int
    2. Argument: std::vector<float>
    Was soll nun T sein? int oder float ? Ist nicht klar, daher der Fehler.
    Deshalb muss man 2.0f angeben, damit beide Typen float sind und es keinen Fehler gibt, bzw. eindeutig ist.

    Grüssli


Anmelden zum Antworten