Template-Spezialisierung: const char* const& --> Linker-Fehler
-
Bei VC++ und BCB gibt folgendes nen Linker-Fehler:
template< typename T> void foo( const T& t); template<> void foo( const char*const&) { } int main() { foo( "bla"); }Fehlermeldung bei VC:
Nicht aufgelöstes externes Symbol '"void __cdecl foo<char const [4]>(char const (&)[4])" (??$CBD@Z)', verwiesen in Funktion '_main'
Den BCB 'überred ich dazu, wenn ich
template<> void foo( char*const&) { }mache. Warum auch immer. Bei VC++ ändert das aber auch nix.
Was mach ich, wenn meine Template-Funktoin const T& kriegt, ich das ganze aber für T=const char* spezialisieren muss???
-
Willst du ne Refernz auf nen Pointer, nen const Pointer auf ne konstante Zeichenkette oder ganz einfach nur nen konstanten C-String empfangen?
In der Reihenfolge und ohne Garantie, bin hundemüde:template<> void foo(const char *& const str) { //..irgendwas machen } template<> void foo(const char * const str) { //..irgendwas machen } template<> void foo(const char *str) { //..irgendwas machen }
-
Ich will eigentlich nur einen ganz normalen konstanten oder nicht konstanten C-String übergeben.
Das Problem ist, dass die vorgegebene Template-Funktion schon fest legt, dass es eine const Ref ist. -> Logisch wär const char*const&. Und eine const Referenz auf einen Zeiger müsste doch im Endeffekt dasselbe sein wie der Zeiger.
-
Ich will eigentlich nur einen ganz normalen konstanten oder nicht konstanten C-String übergeben.
Das Problem ist, dass die vorgegebene Template-Funktion schon fest legt, dass es eine const Ref ist. -> Logisch wär const char*const&. Und eine const Referenz auf einen Zeiger müsste doch im Endeffekt dasselbe sein wie der Zeiger.Versuchs jetzt mit ner normalen Überladung
void foo(const char *) { //..irgendwas machen } //oder template<> void foo(const char * const&) { //..irgendwas machen }Geht beides. Im Beispiel ... Mal schauen, was ich mir damit für neue Probs einhandle.
-
Funktionen müssen so gut wie nie spezialisiert wrden.
-
Außer, wenn man z.B. den Rückgabewert festlegen will (ich hab in wirlichkeit mehrere Template-Parameter). Aber ich kann auch ne Ausnahme machen und für const char* überladen.
Prinzipiell tät mich aber schon interessieren, warum das nicht geht. Standard-Conform wärs ja wohl, oder?
Voila:
7,8 h für die Portierung eines nicht so kleinen Konsolen-Projekts von Borland C++-Builder 5.5 nach VC 7.1. Zumindest compiliert und linkt es jetzt. 0 Fehler, 0 Warnungen. Hoffe keine Laufzeitfehler eingebaut zu haben. *puh* (ich mach das bestimmt nicht freiwillig)
-
Warum - du hast doch gesagt, dass überladen reicht.
-
Ja es geht, ist aber nicht analog zu anderen Teilen der Bibliothek und deswegen nicht so schön. Außerdem wird die Bibliothek in mehreren Projekten eingesetzt und und ich muss jetzt wegen des Verhaltens von VC und einer einzigen Applikation die Bibliothek ändern, ne neue Version rausbringen etc.. Und ich möcht wissen, warum es nicht geht, abgesehen davon, dass ichs umgehen kann.
-
(Sorry, dass fällt mir erst jetzt ein)
Dann geh über strukturen:namespace help { template<class T,class U> struct specialise_h { typedef void ret; static ret foo(T t,U u) { //... }; }; template<class T,class U> struct specialise_h<const T&, U> { typedef bool ret; ret foo(const T& t,U u) { //... return x; }; }; }; template<class T,class U> typename help::specialie_h<T,U>::ret foo(T t,U u) { return help::specialise_h::foo(t,u); };
-
Prinzipiell tät mich aber schon interessieren, warum das nicht geht. Standard-Conform wärs ja wohl, oder?
Das geht nicht, da bei Referenzparametern in Templates kein "decaying" stattfindet.
Was soviel bedeutet wie, dass ein Array in diesem Fall nicht in "Zeiger auf das erste Element" zerfällt. Dies wäre aber nötig, da ein Stringliteral den Typ const char[] hat und nicht const char*.Für ein Stringliteral wird hier also das Base-Template und nicht die Spezialisierung ausgewählt. Weist du hingegen das Stringliteral zuvor einer Variablen vom Typ const char* zu, dann wird auch die Spezialisierung aufgerufen.
-
Heißt das, er müsste noch für const char[] spezialisieren?
-
ness schrieb:
Heißt das, er müsste noch für const char[] spezialisieren?
Der Typ von T ist hier const char[N], wobei N die Länge des Stringliterals ist. Für diesen Typen kannst du die Funktion so aber nicht spezialisieren, da du N nicht zur Verfügung hast.
Also: solange das Base-Template einen Referenzparameter enthält ist eine Spezialisierung für Stringliterale nicht möglich, da es für Funktionen keine partielle Spezialisierung gibt.
Man könnte die Funktion allerdings entsprechend überladen:
template <int N> void foo(const char (&a)[N]);Wobei eine Überladung für const char* hier sicher angebrachter wäre.
-
Wenn er sicher gehen möchte soll er doch ne ganz normale Funktion draus machen.
Bei der Auflösung von Überladungen spielen doch die spezialisierten Versionen erst dann eine Rolle wenn das "passenste" base template gefunden wurde.Wenn es von diesem base Template eine passende Spezialisierung gibt wird diese genommen und ansonsten eine generiert.
Die ganze Spezialisierung von Funktionstemplates verhält sich etwas "unnatürlich".MfG Spacelord
-
Überladen hab ich inzwischen. Und verstanden warum ichs machen muss auch. Danke!
