template in namespace
-
ich probiere gerade eine funktion mit einer Template Variable in einen Namespace zu packen und scheitere dabei:
namespace mathext { template <typename T> T sgn(T); } // End of namespace "mathext"
T ::mathext::sgn(T); { if (x>0) return( 1.0); else if (x<0) return(-1.0); else return( 0.0); }
liefert mir den Fehler
src\mathext.cpp:47: error: `T' has not been declared
Was mache ich falsch?
Matthias
-
template<typename T> T mathext::sgn( T ) { ... }
-
Nanana wer will denn da definition und decleration bei Templates trennen? Das ist aber böse
#if !defined(MATH_EXT_HPP__INCLUDED) #define MATH_EXT_HPP__INCLUDED namespace math { template <typename value_type> inline void sgn(value_type const& data) { return (data > 0 ? 1 : (data < 0 ? -1 : 0)); } }; // math #endif // MATH_EXT_HPP__INCLUDED
-
(D)Evil schrieb:
Nanana wer will denn da definition und decleration bei Templates trennen? Das ist aber böse
Das heißt ich kann grundsätzlich nicht in .h und .cpp Datei Trennen, sobald ich templates nehmen ?
Matthias
-
#ifndef ... #define ... namespace mathext { template<typename T> T sgn(T); } template<typename T> T mathext::sgn( T ) { ... } #endif
Lässt sich durchaus machen
Manche packen die Template-Definitionen in eine extra Datei und '#include'n die einfach unterhalb der Template-Deklarationen. So hat man halt auch Deklaration und Definition getrennt, jedenfalls optisch (und darauf kommt's ja oft an).
-
pospiech schrieb:
(D)Evil schrieb:
Nanana wer will denn da definition und decleration bei Templates trennen? Das ist aber böse
Das heißt ich kann grundsätzlich nicht in .h und .cpp Datei Trennen, sobald ich templates nehmen ?
Matthias
Das stimmt, die Definition (also der Quellcode innerhalb der Funktion) muss schlussendlich durch Includes oder wie auch immer in der verwendenden Datei landen.
-
template-export ...
-
Jetzt bekomme ich einen neuen Fehler, wobei ersted in der .h und zweites in der .cpp Datei steht
namespace mathext { template <typename T> T sgn(const T); } template<typename T> T mathext::sgn(const T) { return (T > 0 ? 1 : (T < 0 ? -1 : 0)); }
Fehler:
src\mathext.cpp: In function
T mathext::sgn(T)': src\\mathext.cpp:49: error: expected primary-expression before '>' token src\\mathext.cpp:49: error:
T' is not a template
src\mathext.cpp:49: error: missing `>' to terminate the template argument list
src\mathext.cpp:49: error: expected primary-expression before ')' tokenMatthias
-
return (T > 0 ? 1 : (T < 0 ? -1 : 0));
Hier hat (D)Evil wohl einfach den Typ als Variable benutzt (müde? :p), muss natürlich
template<typename T> T mathext::sgn(const T t) { return (t > 0 ? 1 : (t < 0 ? -1 : 0)); }
heißen
-
Badestrand schrieb:
return (T > 0 ? 1 : (T < 0 ? -1 : 0));
Hier hat (D)Evil wohl einfach den Typ als Variable benutzt (müde? :p), muss natürlich
template<typename T> T mathext::sgn(const T t) { return (t > 0 ? 1 : (t < 0 ? -1 : 0)); }
heißen
warum eigentlich T als Rückgabetyp?
template<typename T> int mathext::sgn(const T& t) { return (t>=0)-(t<=0); }
-
(D)Evil schrieb:
Nanana wer will denn da definition und decleration bei Templates trennen?
Was spricht denn prinzipiell dagegen? Klar, es sollte trotzdem 'inline' sein wegen der ODR. Aber aus Gründen der Übersichtlichkeit (oder der Vorwärtsdeklaration!) kann es doch durchaus sinnvoll sein, die Funktionen erst zu deklarieren und dann zu implementieren.
-
Konrad Rudolph schrieb:
(D)Evil schrieb:
Nanana wer will denn da definition und decleration bei Templates trennen?
Was spricht denn prinzipiell dagegen? Klar, es sollte trotzdem 'inline' sein wegen der ODR. Aber aus Gründen der Übersichtlichkeit (oder der Vorwärtsdeklaration!) kann es doch durchaus sinnvoll sein, die Funktionen erst zu deklarieren und dann zu implementieren.
Was hat inline bei Funktionstemplates mit der ODR zu tun?
-
camper schrieb:
Was hat inline bei Funktionstemplates mit der ODR zu tun?
Es geht nicht um die Funktionstemplates sondern um die Tatsache, dass die Definition im Header steht und der Header ja an mehrern Stellen eingebunden werden kann.
-
Konrad Rudolph schrieb:
camper schrieb:
Was hat inline bei Funktionstemplates mit der ODR zu tun?
Es geht nicht um die Funktionstemplates sondern um die Tatsache, dass die Definition im Header steht und der Header ja an mehrern Stellen eingebunden werden kann.
Dann verstehe ich nicht, was du mit
Klar, es sollte trotzdem 'inline' sein wegen der ODR.
sagen willst.
-
camper schrieb:
Konrad Rudolph schrieb:
camper schrieb:
Was hat inline bei Funktionstemplates mit der ODR zu tun?
Es geht nicht um die Funktionstemplates sondern um die Tatsache, dass die Definition im Header steht und der Header ja an mehrern Stellen eingebunden werden kann.
Dann verstehe ich nicht, was du mit
Klar, es sollte trotzdem 'inline' sein wegen der ODR.
sagen willst.
Und ich verstehe wiederum nicht, was Du daran nicht verstehst. Wenn die Funktion nicht 'inline' ist und Du sie in mehrere Übersetzungseinheiten einbindest, knallt's.
-
Konrad Rudolph schrieb:
camper schrieb:
Konrad Rudolph schrieb:
camper schrieb:
Was hat inline bei Funktionstemplates mit der ODR zu tun?
Es geht nicht um die Funktionstemplates sondern um die Tatsache, dass die Definition im Header steht und der Header ja an mehrern Stellen eingebunden werden kann.
Dann verstehe ich nicht, was du mit
Klar, es sollte trotzdem 'inline' sein wegen der ODR.
sagen willst.
Und ich verstehe wiederum nicht, was Du daran nicht verstehst. Wenn die Funktion nicht 'inline' ist und Du sie in mehrere Übersetzungseinheiten einbindest, knallt's.
Keineswegs.
Templates dürfen in einem Programm mehrfach definiert werden, sofern jede Definition in einer anderen Übersetzungseinheit auftaucht (und noch ein paar zusätzliche Bedingungen erfüllt sind, die, ohne ins Detail zu gehen, darauf hinauslaufen, dass jede Definition die gleiche Bedeutung haben muss).
Funktionen dürfen nicht mehrfach definiert werden.Eine Templatedefinition ist aber keine Funktionsdefinition. Eine Templatespezialierung des gleichen Templates darf in mehreren Übersetzungseinheiten mit den gleichen Templateparametern instantiiert werden ohne die ODR zu verletzen - welche Instanz benutzt wird bleibt unspezifiziert (sie müssen ja sowieso alle gleich sein).
Eine explizite Spezialisierung eines Templates ist kein Template.
Demzufolge darf die Definition einer expliziten Spezialisierung eines Funktionstemplates nur einmal erfolgen (weil es eine Funktionsdefinition ist) oder muss inline sein, wenn man diese Definition ebenfalls im Header durchführen will, weil sie logisch zur Templatedefinition gehört.
-
camper, Du hast natürlich mit Cruise-Missile-Genauigkeit auf meinen Fehler zugesteuert.
Klar. Danke.
-
camper schrieb:
...- welche Instanz benutzt wird bleibt unspezifiziert (sie müssen ja sowieso alle gleich sein)...
Mal eine Frage aus Neugier: Stellt der Compiler/Linker das irgendwie sicher ? Und wenn ja: Wie wird das üblicherweise gemacht ?
Gruß,
Simon2.
-
Simon2 schrieb:
Mal eine Frage aus Neugier: Stellt der Compiler/Linker das irgendwie sicher ? Und wenn ja: Wie wird das üblicherweise gemacht ?
Interessante Frage, die mich dazu verleitet hat, das ganze mal mit dem gcc 4.1 auszuprobieren. Folgende Quelltexte sind gegeben:
// file1.cpp #include <iostream> extern void xy(); template<typename T> T hallo() { return 3; } int main() { std::cout << hallo<int>() << std::endl; xy(); } // file2.cpp #include <iostream> template<typename T> T hallo() { return 2; } void xy() { std::cout << hallo<int>() << std::endl; }
Ausgabe ohne Inline-Expansion, wenn file1.o vor file2.o gelinkt wird: 3, 3
Ausgabe ohne Inline-Expansion, wenn file2.o vor file1.o gelinkt wird: 2, 2
Ausgabe mit Inline-Expansion: 3, 2Er stellt also offensichtlich garnichts (zuverlässig) sicher, sondern nimmt die erste Definition, die beim Linken auftaucht (wenn der Compiler nicht geinlined hat).
-
LordJaxom schrieb:
Er stellt also offensichtlich garnichts (zuverlässig) sicher, sondern nimmt die erste Definition, die beim Linken auftaucht (wenn der Compiler nicht geinlined hat).
sei froh, dass er das macht und dir nicht der himmel auf den kopf fällt.