Implizite Typenumwandlung aktivieren.



  • Gibt es eine Möglichkeit eine Typenumwandlung implizit zu ermöglichen?
    In etwa so:

    class A
    {
        // ... 
    };
    class B
    {
        // ...
    };
    
    //  in etwa so (Konvertierungsoperator, funktioniert leider nur als nicht 
    //  statische Methode einer Klasse)
    operator A*(B* pB)
    {
        // konvertiere B* nach A*, wie auch immer, z.B.:
        return reinterpret_cast<A*>(pB);
    }
    //  die Konvertierung zu einer Klasse kann man auch über einen ctor regeln, 
    //  allerding sind Zeiger keine Klassen
    //  auch der assign operator muss muss eine nicht-statische Methode einer Klasse sein
    //  mir fällt keine weitere Möglichkeit ein, gibt es etwa keine? );
    

    Einige scheinen ja alle Features von C++ zu kennen.
    Vielleicht kann auch jemand begründen, warum diese Operatoren nur als Methoden arbeiten?

    Danke.



  • Die implizite Konvertierung von Zeigern zweier Klassen kannst du nur durch Vererbung ermöglichen (und dann auch nur in eine Richtung!).


  • Mod

    Dafür gibt es keine Möglichkeit (man denke aber auch an smartpointer 😉 )
    Der Grund dafür ist, dass die Sprachmittel zum Definieren neuer Typen und Überladen von Operatoren die Sprache nur erweitern aber nicht verändern sollen. Daher muss bei jeder Operatorenüberladung wenigstens ein Parameter ein UDT sein. Konversionsoperatoren nehmen in diesem Sinne noch eine Sonderrolle ein. Aber jedenfalls stehen die Konvertierungsregeln zwischen verschiedenen Pointern bereits fest - könnte man hier durch Konversionsoperatoren etwas machen, liefe das auf eine (nicht gewollte) veränderung hinaus.



  • Hm, okay, das habe ich mir fast schon gedacht.
    Also, wenn ich eine Templateklasse habe,
    z.B.

    template <class T, int n, int m>
    class CMatrixT
    {
    public: // ganz viele funktionen zum arbeiten mit (n,m)-Matrizen
    
    private:
        T    m_components[n][m];
    };
    

    und eine einfache C-Struktur:

    struct C4x4Matrix
    {
        float components[4][4];
    };
    

    dann habe ich ein Problem, bzw. plage mich ziehmlich mit reinterpret_cast's, die ziehmlich unschön sind. Die C-Struktur brauche ich für meine Schnittstelle, die template-Klasse verwende ich intern.
    Es soll jetzt also die template-Klasse von der C-Strukur abgeleitet werden, quasi eine Wrapper-Klasse.
    Dann könnte ich doch folgendes machen?

    //	generate compile time error, if bAssumedTrue
    template <bool bAssumedTrue> class CCompileTimeAssertT
    {   int unused[bAssumedTrue ? 1 : -1];   };
    
    template <class T1, class T2> 
    void ProcCompileTimeAssertTypesRelated(T1& t1, T2& t2)
    {
        T1& p1 = static_cast<T1&>(t2);
        T2& p2 = static_cast<T2&>(t1);
        p1; p2; t1; t2;
    }
    
    template <class T1, class T2> 
    void ProcCompileTimeAssertTypesRelated(T1 t1[], T2 t2[])
    {
        T1& p1 = static_cast<T1&>(t2[0]);
        T2& p2 = static_cast<T2&>(t1[0]);
        p1; p2; t1; t2;
    }
    
    template <class T1, class T2>
    class _validateType
    {
    public:
        _validateType()
        {
            CCompileTimeAssertT<sizeof(t1.value) == sizeof(t2.value)>
                _Error_Base_value_has_wrong_size; _Error_Base_value_has_wrong_size;
            CCompileTimeAssertT<sizeof(T1) == sizeof(T2)>
                _Error_Base_has_wrong_size;       _Error_Base_has_wrong_size;
            ProcCompileTimeAssertTypesRelated(t1.value, t2.value);
        }
    
    private:
    	T1 t1;
    	T2 t2;
    };
    
    //	Matrizen
    template <class T, int n, int m>
    struct CMatrixBaseT
    {    T    value[n*m];	};
    
    template <class T, int n, int m, class Base = CMatrixBaseT<T, n, m> >
    class CMatrixT : public Base
    {
    public: // ganz viele funktionen zum arbeiten mit (n,m)-Matrizen
        CMatrixT()
        {   _validateType<Base, CMatrixBaseT<T, n, m> >	validate;  }
    };
    
    //	Skalare
    template <class T>	struct CScalarBaseT
    {    T value;	};
    
    template <class T, class Base = CScalarBaseT<T> >
    class CScalarT : public Base
    {
    public: // ganz viele funktionen zum arbeiten mit Skalaren
        CScalarT()
        {   _validateType<Base, CScalarBaseT<T> >	validate; }
    };
    
    extern "C"    //  C-Strukturen
    {
    struct Scalar
    {   float	   value;        };
    
    struct Matrix4x4
    {   Scalar  value[4*4];   };
    }
    
    //	typedefs
    typedef CScalarT<float, Scalar>               MeinScalar;
    typedef CMatrixT<MeinScalar, 2, 8, Matrix4x4> MeineMatrix;
    
    //	Verwendung
    MeinScalar   x;
    MeineMatrix  y;
    Matrix4x4*   p1 = &y;
    MeineMatrix* p2 = static_cast<MeineMatrix*>(p1);
    

    Dann ist die Konvertierung in die eine Richtung schonmal implizit. Allerdings tun sich jetzt Abründe auf:
    die Base muss einen member mit genau vorgegebener Größe haben und mit genau festgelegtem Typ. Das ganze wird abgesichert, würde also bereits zur Compilierzeit als Murks entarnt werden können.
    Ein paar einfache Konvertierungen kann man da jetzt ja einbauen, allerdings muss ich von C4x4Matrix* nach MeineMatrix* einen static_cast verwenden.
    Gibt es dafür eine elegantere Lösung?
    Oder sonstige Anregungen. Die _validateType Klasse erscheint mir auch im Zwielicht, denn ihr konstruktor wird aufgerufen. (der Compiler _kann_ das optimieren, allerdings testet man Programme auch gern ohne Optimierungen.

    MfG
    DDR-RAM


Anmelden zum Antworten