template Zeiger; Compiler will reinterpret_cast



  • Hi, folgender Code:

    template<typename typeA> class A {
    
        template<typename typeB> class B;
    
        B<typename> *_B;
    
        void test() {
            _B = B<float>::getInstance();
        }
    };
    

    Ein Aufruf durch z.B. ein A<unsigned> Objekt ergibt:

    1>(8) : error C2440: '=' : cannot convert from 'A<typeA>::B<typeB> *' to 'A<typeA>::B<typeB> *'
    1>        with
    1>        [
    1>            typeA=unsigned int,
    1>            typeB=float
    1>        ]
    1>        and
    1>        [
    1>            typeA=unsigned int,
    1>            typeB=int
    1>        ]
    1>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
    

    Kann mir nur vorstellen dass meine Syntax in Zeile 5 daneben liegt aber find auch keine andere Lösung.



  • NatOp schrieb:

    Kann mir nur vorstellen dass meine Syntax in Zeile 5 daneben liegt aber find auch keine andere Lösung.

    Da du in Zeile 5 eine Variable deklarierst, musst du da imho auch den Template-Parameter angeben. Willst du evtl B<typeA> *_B; ?



  • eben nicht; der typ von B wird erst beim Konstruktoraufruf von A klar

    edit: also eher

    template<typename typeA> class A { 
    
        template<typename typeB> class B; 
    
        B<typename> *_B; 
    
        A<typeA>() { 
            _B = B<float>::getInstance(); 
        } 
    
        /**
         * wie "setze" ich nun typeB richtig, 
         * damit es auch spaeter geaendert werden kann?
         */
    
        void setB(string bla) {
            if (!bla.compare("blub")) {
                _B = B<double>::getInstance();
            }
        }
    
    };
    


  • NatOp schrieb:

    eben nicht; der typ von B wird erst beim Konstruktoraufruf von A klar

    Bist du dir da sicher? Mir wäre das jedenfalls neu, C++ ist ja statisch typisiert und bei zwei verschiedenen Konstruktoraufrufen mit unterschiedlicher Initialisierung (obwohl du in deinem Konstruktor ja eh nur eine Zuweisung hast) wäre der Typ nicht besonders "klar".

    Mir scheint, als würde der Compiler bei B<typename> *_B; automatisch int als Template-Parameter nehmen. Wenn der Typ vorher nicht klar ist, verwende (Laufzeit-)Polymorphie; so wie du das hier vorhast, funktioniert es imho nicht.

    edit: Bin mir sicher, dass es so nicht funktioniert. Du kannst zur Laufzeit einfach nicht den Typ von _B verändern, ebenso wenig wird er erst bei der Initialisierung klar.
    edit2: Was willst du mit dem Code denn erreichen? Gibt sicherlich einen anderen Weg.



  • Badestrand schrieb:

    edit2: Was willst du mit dem Code denn erreichen? Gibt sicherlich einen anderen Weg.

    Klasse A speichert über ein Array vom Typ typeA irgendwas ab, z.B. vom Typ unsigned int.
    Man soll nun von Klasse A beliebig oft einen Pointer auf eine Instanz der Klasse B kriegen können;
    stimmt der aktuelle Typ der Singleton-Instanz in B nicht mit der von getInstance überein, wird eine neue Instanz mit neuem Typ erstellt und die alten Werte übernommen.
    Das ganze hat den Sinn, dass man für A zum Speichern von Daten "kleine" Typen nehmen kann,
    um auf ihnen dann komplexe Operationen auszuführen, können in B auf temporären double oder long Arrays gerechnet werden.



  • Wäre dann nicht vielleicht sowas sinnvoller?:

    template<typename T> class LittleArrayHolder
    {
        public:
    		template<typename U> void DoTransformations()
    		{
    			std::vector<U> big_vals( m_aValues.begin(), m_aValues.end() );
    			// Irgendwas damit machen
    			m_aValues.swap( std::vector<T>( big_vals.begin(), big_vals.end() ) );
    		}
    
    		// Oder, ohne Warnungen:
    		template<typename U> void DoTransformations2()
    		{
    			std::vector<U> big_vals;
    			big_vals.reserve( m_aValues.size() );
    			for ( std::vector<T>::const_iterator valIter=m_aValues.begin(); valIter!=m_aValues.end(); valIter++ )
    				big_vals.push_back( static_cast<U>(*valIter) );
    
    			// Irgendwas damit machen
    
    			for ( std::vector<U>::size_type i=0; i<big_vals.size(); i++ )
    				m_aValues[i] = static_cast<T>( big_vals[i] );
    		}
    
    	private:
    		std::vector<T> m_aValues;
    };
    

    Bleibt dem Anwender natürlich die Verantwortung überlassen, dass er auch die richtigen Typen übergibt. Wäre das in etwa das, was du vorhattest?



  • hm ok vielen dank, nettes konstrukt.
    werd na gucken wie ich klarkomm


Anmelden zum Antworten