@Hume
-
Servus Hume!
Kurz zur Erinnerung:
Thema: std::string & +-Operator std::string & +-OperatorIch hab nach deinem Vorschlag den Additionsoperator nochmals global überladen. Der BorlandCompiler ist damit allerdings nicht ganz einverstanden("Mehrdeutigkeit zwischen operator ... und ..."). Ich vermute das es daran liegt, dass im BCB6 bereits die STLPort-Bibliothek implementiert ist. Alles deutet darauf hin, dass ein TemplateOperator '+' bereits existiert. Und ein mehrfaches Überladen einer konkreten OperatorImplementierung ist ja nicht zulässig. Ob ich wirklich richtig liege, werd ich erst erfahren, wenn ich mir die STLPort etwas näher betrachtet habe. Aber eine Meldung wie "Mehrdeutigkeit zwischen .." und "ambiguous overloading ..." muss eigentlich darauf zurückzuführen sein, dass die betroffene Implementierung bereits existiert. Das gilt ja auch für Templates.
Soviel nur zur Info!Bis denn dann.
Grüße,
TS++
-
Hallo,
deine Schlussfolgerung halte ich für zweifelhaft.Schließlich existiert in *jeder* konformen STL-Implementation ein Template-Op+. Mir scheint es wahrscheinlicher, dass dein Compiler kein partial ordering von Funktionstemplates unterstützt. In diesem Fall kannst du den von mir geposteten Code vergessen.
-
Hallo Hume!
Heißt da jetzt, ich kann einen TemplateOperator jederzeit mehrfach überladen aber eine Implementierung eines Operators für einen konkrete Fall nur einmal?
Unter DevC++ hab ich's auch ausprobiert und da hat er mir ebenfalls die Meldung "ambiguous overloading" gebracht als ich einen TemplateOperator erneut global überladen wollte.
Grüße,
TS++
-
Hallo,
nein du kannst natürlich nicht zweimal den den *gleichen* op+ überladen. Du darfst auch nicht zwei Überladungen basteln, die für ein gegebenes T äquivalente Herleitungen produzieren.Das Problem hier ist aber (denke ich), dass viele Compiler sowas nicht unterscheiden können:
template <class T> void func(T p) {} template <class T> void func(T* p) {}
In diesem Fall käme es bei dem von mir geposteten Code sofort zu Mehrdeutigkeiten.
Unter DevC++ hab ich's auch ausprobiert und da hat er mir ebenfalls die Meldung "ambiguous overloading" gebracht als ich einen TemplateOperator erneut global überladen wollte.
Welche Version des Compilers? Welcher Code? Welcher Aufruf?
-
BloodShed DevC++ 4
Mingw compiler 2.95.2-1 MSVCRT + updated headers and libraries
GNU debugger 4.18(ein Beispiel, bei dem ich mehrfaches Überladen von TemplateOperatoren provoziere, hat tatsächlich den erwarteten Effekt => Mehrdeutigkeit.
Dein Code wiederum läuft beim DevC++ problemlos)Ich glaub so langsam steig ich dahinter, weshalb das erneute Überladen des Additionsoperators für Elemente vom Typ T zumindest beim DevC++ möglich ist, das grundsätzliche mehrfache Überladen von TemplateOperatoren aber nicht.
Ich hab mir mal den basic_string etwas näher angeschaut und festgestellt, dass ,wie du gesagt hast, ein Template Operator '+' für einen variablen Typ(hier charT) tatsächlich schon in basic_string implementiert ist.
template <class charT, class traits, class Alloc> basic_string<charT, traits, Alloc> operator+(charT c, const basic_string<charT, traits, Alloc>& s2) template <class charT, class traits, class Alloc> basic_string<charT, traits, Alloc> operator+(const basic_string<charT, traits, Alloc>& s1, charT c)
Also würde man ja zunächst annehmen, dass das erneute globale Überladen, wie du es vorgeschlagen hast, nicht möglich sein dürfte. Geht aber beim DevC++ trotzdem.
Ich hab jetzt eine Vermutung warum das so ist (ist aber nur ne Vermutung, ich bin kein Sprachen/Formate-Experte)
Die StringKlasse meiner Wahl wird ja erst mit der Nutzung der Klasse erzeugt.
Über std::string myString wird eine Typenangabe in <string> genutzt, die automatisch charT auf char setzt. Was ich erzeuge ist ja eigentlich folgendes:
basic_string<char> myString;
Die Klasse basic_string<char> verfügt nun aber nicht mehr über den bereits erwähnten völlig freien Templateoperator + für einen Typ T. Alles was existiert, sind Implementierungen für char und char*. Ich kann also problemlos den Additionsoperator global für einen Typen T überladen.Jetzt ist natürlich noch die Frage, warum der BCB damit nicht zurechtkommt?
Man kann ja nicht gerade behaupten, dass Borland eine NoNameFirma ist. Vielleicht liegts ja am STLPort!?Mal schaun.
Grüße,
TS++
-
Ach weil's mir noch einfällt:
Vielleicht sollte man den Code für das globale Überladen noch etwas abwandeln.template <class T> string operator+(const string& lhs, T t) { ostringstream str; str << t; return lhs + str.str(); } template <class T> string operator+(T t, const string& rhs) { ostringstream str; str << t; return str.str() + rhs; }
Bei der vorherigen Version würde ich ja sonst wirklich alle verwendeten basic_string-Varianten einbeziehen. Evtl. auch solche die charT nicht durch char ersetzen.
Grüße,
TS++
-
Vielleicht sollte man den Code für das globale Überladen noch etwas abwandeln.
Nein das sollte man nicht. In diesem Fall wäre der op+ nämlich in der Tat mehrdeutig.
Hier:
return lhs + str.str();
könnte nämlich:
1. der vorhandene Template-Op aufgerufen werden
2. der neue Template-Op.Bei zweiterem passt nämlich dann der erste Parameter besser (kein Template). Bei ersterem der zweite (spezieller).
Ich hab mir mal den basic_string etwas näher angeschaut und festgestellt, dass ,wie du gesagt hast, ein Template Operator '+' für einen variablen Typ(hier charT) tatsächlich schon in basic_string implementiert ist.
charT ist nicht wirklich variabel sondern abhängig vom Zeichentyp des Strings. In der Regel also nur char bzw. wchar_t.
Jetzt ist natürlich noch die Frage, warum der BCB damit nicht zurechtkommt?
Wenn mich nicht alles täuscht habe ich diese Frage schon beantwortet.
Es gibt Compiler für die die folgenden beiden op+ gleich gut sind:// op+ aus <string> template <class Char, class Trait, class Alloc, class T> basic_string<Char, Trait, Alloc> operator+(const basic_string<Char, Trait, Alloc>& lhs, basic_string<Char, Trait, Alloc>& rhs) // eigener op+ template <class Char, class Trait, class Alloc, class T> basic_string<Char, Trait, Alloc> operator+(const basic_string<Char, Trait, Alloc>& lhs, T t)
Über std::string myString wird eine Typenangabe in <string> genutzt, die automatisch charT auf char setzt
std::string ist nichts weiter als ein Typedef für std::basic_string<char, std::char_traits<char>, std::allocator<char> >.
Man kann ja nicht gerade behaupten, dass Borland eine NoNameFirma ist.
Das heißt natürlich überhaupt nichts. Microsoft ist auch keine NoNameFirma. Der VC 6 kann das trotzdem nicht. Relevant ist hier nicht der Name der Firma sondern einzig die Templateunterstützung des Compilers. Und die ist bei vielen Compilern schlicht und einfach etwas hinter der Zeit.
-
Ok, nur folgendes ist mir noch nicht so ganz klar:
In diesem Fall wäre der op+ nämlich in der Tat mehrdeutig.
Hier:
return lhs + str.str();
könnte nämlich:
1. der vorhandene Template-Op aufgerufen werden
2. der neue Template-Op.Wie läuft denn prinzipiell die Klassengenerierung ab?:
1. basic_string<char> str; //charT wird durch char ersetzt //=> es entsteht eine neue basic_string-Variante //deren Additionsoperator nur mit char* und //basic_string<char> arbeitet. 2. str+1; //Additionsoperator mit int existiert noch nicht. //Es gibt nur noch einen passenden Template- //operator und der ist global. //=> Variante des global überladenen Operators // mit int wird erzeugt 3. In der Routine des globalen Operators für int: basic_string<char> operator+(const basic_string<char>& lhs, int t) { ostringstream stream; stream<<t; return(lhs+stream.str()); //Additionsoperator für basic_string<char> //existiert bereits eindeutig in //basic_string<char>. } //Es dürften doch eigentlich keine Mehrdeutigkeiten auftreten, oder?
Grüße,
TS++[ Dieser Beitrag wurde am 07.07.2003 um 15:10 Uhr von TS++ editiert. ]
-
//=> es entsteht eine neue basic_string-Variante
//deren Additionsoperator nur mit char* und
//basic_string<char> arbeitet.Es gibt zwei die const char* erwarten und zwei die char erwarten. Keinen der char* erwartet. Und erzeugt werden die natürlich nur, wenn sie auch tatsächlich gebraucht werden.
//Additionsoperator für basic_string<char>
//existiert bereits eindeutig in
//basic_string<char>.Nope. Der op+ für zwei basic_strings ist ein Nonmember. Er liegt also nicht in der Klasse basic_string sondern im Namensraum std.
//Es dürften doch eigentlich keine Mehrdeutigkeiten auftreten, oder?
Richtig. Sonst hätte ich den Code ja auch nicht gepostet
-
Ok, danke Hume.
Damit müsste eigentlich alles klar sein.Ich werd auf jeden Fall auch mal in der Borland Community posten. Ich kann mir einfach nicht vorstellen, dass man sich dort nur wenige oder gar keine Gedanken zu diesem Thema gemacht hat. Eigentlich enttäuschend, das die STL beim Thema Strings, verglichen mit anderen Sprachen, eine derartige Flickschusterei zu bieten hat. Hätte man den TemplateOperator '+' in basic_string beim Ersatz von charT durch char einfach außen vor gelassen und einen anderen Templatetyp T gesetzt dann hätte man alle nur erdenklichen Implementierungen bereits in basic_string einbauen können. U.a. dann eben auch die Addition mit allen intrinsischen Datentypen und ich müsste mich jetzt nicht mit Compilerspezifischen Problemen herumärgern. Vielleicht ist es sogar das Beste wenn man eine eigene Stringklasse entwickelt, die std::string kapselt. Dann kann der Compiler auch nicht mehr motzen. Ich hätte nie gedacht, dass ich das mal sagen würde, aber da hat man sich außnahmsweise mal bei Java mehr Gedanken gemacht als bei C++.
Grüße,
TS++
-
Heureka!
Ich hab endlich rausgekriegt, was den BorlandCompiler stört:
[cpp]template <class _CharT, class _Traits, class _Alloc, class T>
basic_string<_CharT,_Traits,_Alloc> operator+
(const basic_string<_CharT,_Traits,_Alloc>& __x, const T& t)
{
ostringstream stream;
stream<<t;
return(__x+stream.str());
}
template <class Char, class Trait, class Alloc, class T>
basic_string<Char, Trait, Alloc> operator+
(const basic_string<Char, Trait, Alloc>& lhs, T t)
{
ostringstream str;
str << t;
return lhs + str.str();
}[/cpp]
Ich hab mich mal an der Implementierung im STLPort orientiert, und festgestellt, dass für den Typ T bzw. für _charT eine konstante Referenz gefordert wird.
Jetzt funktionierts!Grüße,
TS++[ Dieser Beitrag wurde am 07.07.2003 um 21:42 Uhr von TS++ editiert. ]