Template Linker Error



  • Hallo allerseits,

    heute hab ich meine ersten Gehversuche mit Templates gestartet, jedoch steh ich vor einem etwas kuriosen Problem.

    Das hier sind erstmal die sources:

    zahl.h

    #ifndef __ZAHL_H__
    #define __ZAHL_H__
    
    #include <iostream>
    
    using namespace std;
    
    ////////////////////////////////////////////////////////////////////
    
    template <typename C> class Zahl
    {
    private:
    	C wert;
    
    public:
    // Rückgabe	Funktion	Param			Inlinedeklaration
    			Zahl		()					{ wert = 0; };
    			Zahl		(C a)				{ wert = a; };
    
    	void	setValue	(C a)				{ wert = a; };
    	C		getValue	()					{ return (wert); };
    
    	void	Add			(C v)				{ setValue(getValue() + v); };
    	void	Sub			(C v)				{ setvalue(getValue() - v); };
    	void	Mul			(C v)				{ setValue(getValue() * v); };
    	void	Div			(C v)				{ if(v) setValue(getValue() / v); else cout << "Unendlich" << endl; };
    };
    
    template <typename C> Zahl<C> operator +(Zahl<C>, Zahl<C>);
    template <typename C> Zahl<C> operator -(Zahl<C>, Zahl<C>);
    template <typename C> Zahl<C> operator *(Zahl<C>, Zahl<C>);
    template <typename C> Zahl<C> operator /(Zahl<C>, Zahl<C>);
    
    template <typename C> Zahl<C> operator +(C, Zahl<C>);
    template <typename C> Zahl<C> operator -(C, Zahl<C>);
    template <typename C> Zahl<C> operator *(C, Zahl<C>);
    template <typename C> Zahl<C> operator /(C, Zahl<C>);
    
    template <typename C> Zahl<C> operator +(Zahl<C>, C);
    template <typename C> Zahl<C> operator -(Zahl<C>, C);
    template <typename C> Zahl<C> operator *(Zahl<C>, C);
    template <typename C> Zahl<C> operator /(Zahl<C>, C);
    
    #endif // __ZAHL_H__
    

    zahl.cpp

    #include <iostream>
    #include "zahl.h"
    
    using namespace std;
    
    /****************************************************************************************/
    /*                               Operatoren                                             */
    /****************************************************************************************/
    
    template <typename C> Zahl<C> operator +(Zahl<C> a, Zahl<C> b)
    {
    	Zahl<C> tmp(a.getValue() + b.getValue());
    	return (tmp);
    }
    
    template <typename C> Zahl<C> operator -(Zahl<C> a, Zahl<C> b)
    {
    	Zahl<C> tmp(a.getValue() - b.getValue());
    	return (tmp);
    }
    
    template <typename C> Zahl<C> operator *(Zahl<C> a, Zahl<C> b)
    {
    	Zahl<C> tmp(a.getValue() * b.getValue());
    	return (tmp);
    }
    
    template <typename C> Zahl<C> operator /(Zahl<C> a, Zahl<C> b)
    {
    	Zahl<C> tmp(a.getValue() / b.getValue());
    	return (tmp);
    }
    
    //////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////
    
    template <typename C> Zahl<C> operator +(C a, Zahl<C> b)
    {
    	Zahl<C> result;
    	result.setValue(a + b.getValue());
    	return (result);
    }
    
    template <typename C> Zahl<C> operator -(C a, Zahl<C> b)
    {
    	Zahl<C> result;
    	result.setValue(a - b.getValue());
    	return (result);
    }
    
    template <typename C> Zahl<C> operator *(C a, Zahl<C> b)
    {
    	Zahl<C> result;
    	result.setValue(a * b.getValue());
    	return (result);
    }
    
    template <typename C> Zahl<C> operator /(C a, Zahl<C> b)
    {
    	Zahl<C> result;
    	result.setValue(a / b.getValue());
    	return (result);
    }
    
    //////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////
    
    template <typename C> Zahl<C> operator +(Zahl<C> b, C a)
    {
    	Zahl<C> result;
    	cerr << "Grunz" << endl;
    	result.setValue(a + b.getValue());
    	return (result);
    }
    
    template <typename C> Zahl<C> operator -(Zahl<C> b, C a)
    {
    	Zahl<C> result;
    	result.setValue(a - b.getValue());
    	return (result);
    }
    
    template <typename C> Zahl<C> operator *(Zahl<C> b, C a)
    {
    	Zahl<C> result;
    	result.setValue(a * b.getValue());
    	return (result);
    }
    
    template <typename C> Zahl<C> operator /(Zahl<C> b, C a)
    {
    	Zahl<C> result;
    	result.setValue(a / b.getValue());
    	return (result);
    }
    

    main.cpp

    #include <iostream>
    #include "zahl.h"
    
    using namespace std;
    
    int main (int argc, char* argv[])
    {
    	Zahl<double> a(137);
    	Zahl<double> b(63);
    	Zahl<double> c;
    	Zahl<double> d;
    
    	c = a + 42.5;
    	c = 42.5 + a;
    	c = a + 42.0;
    
    	cout << "------------------------------" << endl;
    
    	c = a - 42.5;
    	c = 42.5 - a;
    	c = a - 42.0;
    
    	cout << "------------------------------" << endl;
    
    	c = a * 42.5;
    	c = 42.5 * a;
    	c = a * 42.0;
    
    	cout << "------------------------------" << endl;
    
    	c = a / 42.5;
    	c = 42.5 / a;
    	c = a / 42.0;
    
    	cout << "------------------------------" << endl;
    
    	d = 63.0 + a;
    
    	cout << a.getValue() << endl;
    	cout << b.getValue() << endl;
    	cout << c.getValue() << endl;
    	cout << d.getValue() << endl;
    
    	return (0);
    }
    

    Mein Problem ist es, dass wenn ich das Projekt mit Visual Studio 6 so kompiliere, dass ich diesen Fehler bekomme.

    main.obj : error LNK2001: Nichtaufgeloestes externes Symbol "class Zahl<double>  __cdecl operator/(double,class Zahl<double>)" (??K@YA?AV?$Zahl@N@@NV0@@Z)
    

    Diesen Fehler erhalte ich sowohl mit VS6 als auch dem gcc unter Linux.

    Und das für fast jeden Operator, bis auf die die Objekte Zahl und Zahl erwarten.

    Und das richtig Schlimme ist, dass wenn ich den Inhalt der main.cpp nu an das Ende der zahl.cpp anfüge, dass das ohne weiteres funktioniert. Nicht ein Fehler oder eine Warnung... .

    Plz help.

    MfG

    Vic



  • die implementation muss in zahl.h rein. zahl.cpp kannst du entsorgen.



  • Hi,

    thx für die schnelle Antwort

    Müsste das aber nicht rein theoretisch auch so gehen, weil ich die Definition ja auch in der zahl.h vornehme?

    Aber nochmals THX 😃

    MfG

    BB



  • Vic schrieb:

    Müsste das aber nicht rein theoretisch auch so gehen, weil ich die Definition ja auch in der zahl.h vornehme?

    Welche Definition? Du hast zumindest keine operator Funktionen in der Header-Datei definiert.
    Das Problem ist einfach, dass für eine saubere Trennung von Templates in .h und .cpp das Schlüsselwort export vorgesehen ist. Leider unterstützt das bisher so gut wie kein Compiler (Comeau ist zB 'ne Ausnahme), da es offenbar nicht so einfach zu implementieren ist.


Anmelden zum Antworten