Code für Ausgabe vereinfachen.
-
Dravere schrieb:
audacia schrieb:
operator [] ()gibt eine Referenz zurück, über die du den Wert ändern kannst. Das macht den Unterschied aus.Aber nur der Wert an dieser Stelle. Du kannst nicht vom referenzierten Wert den Zeiger holen, diesen inkrementieren und dann die Stelle beschreiben oder lesen. Das ist undefiniertes Verhalten. Aber genau das macht der präsentierte Code von dir oder der von mir mit
std::fill_n.Das ist mir schon klar. Aber der Rückgabewert des Indexoperators muß praktisch
*const_cast <CharT*> (data () + n)sein - wie von der Definition des Index-Operators gefordert -, unddata()gibt einen Zeiger auf den Datenbestand des Strings in Form eines Arrays zurück. Der Lesezugriff aufconst_cast <CharT*> (data () + n)[1]ist daher legal; der Schreibzugriff zwar nicht, aber in der Praxis existiert keine Prozessorarchitektur, die eine Page-Granularität einzelner Bytes hat, so daß der Schreibzugriff auch fürconst_cast <CharT*> (data () + n)[1]funktionieren wird. Jedoch nicht garantiert ist, daß eine Änderung auf diesem Wege auch den tatsächlichen String ändert - aber wie ich oben schrieb, wäre eine Implementation, die das ausnutzt, am Rande des Wahnsinns.
-
Sebastian Pizer schrieb:
Welche Typsicherheit meinst Du denn? Die Sorte von Typsicherheit, die Typfehler schon zur Kompilierzeit abfangen kann oder nur die Sorte, die Laufzeitüberprüfungen einbaut?
Laufzeitüberprüfung. Die Überprüfung zur Übersetzungszeit ist nicht möglich, wenn der Format-String erst zur Laufzeit bestimmt wird (z.B. mit gettext). Für die Fälle, wo es aber möglich ist, gibt es z.B. -Wformat bei GCC.
unskilled schrieb:
ich nehm mal an, dass ich mich an alles gehalten habe, was im standard steht ^^
Hast du nicht - dein Indexoperator gibt nicht
data()[n]zurück, wie vom Standard gefordert.
-
Aber der Rückgabewert des Indexoperators muß praktisch
*const_cast <CharT*> (data () + n)seinwieso sollte er?
standard, 21.3.4 basic_string element access schrieb:
Returns: If pos < size(), returns *(begin() + pos ). Otherwise, if pos == size(), the const version returns charT(). Otherwise, the behavior is undefined.
das heißt, mein bsp. is doch nich ganz standard-konform, weil ich bei pos==size keine charT() garantieren kann, aber dann muss ich eben doch die 0 mitspeichern und es ist wieder standardkonform
bb
edits: falls es doch iwo steht, dann such ma pls die stelle raus, wo das steht...
das war der working draft, wo das so drin steht ^^
hab ma noch nen älteren standard (wieder nur nen draft-.-) gefunden(eher uralt, weil von 1996 - aber nen besseren hab ich nich gefunden)
da steht das drin:1 Effects: The reference returned is invalid after any subsequent call to c_str(), data(), or any nonconst member function for the object.
2 Returns: If pos < size(), returns data()[pos]. Otherwise, if pos == size(), the const version returns traits::eos(). Otherwise, the behavior is undefined.wenn das noch gültig ist, dann hast du natürlich recht ^^ aber dann kann ich einfach sagen, dass ich nach dem kommenden standard standardkonform wäre

-
unskilled schrieb:
edits: falls es doch iwo steht, dann such ma pls die stelle raus, wo das steht...
das war der working draft, wo das so drin steht ^^
hab ma noch nen älteren standard (wieder nur nen draft-.-) gefunden(eher uralt, weil von 1996 - aber nen besseren hab ich nich gefunden)Hättest du den Thread gelesen, so wäre dir vielleicht aufgefallen, daß ich die entsprechende Stelle oben bereits zitiert habe, und zwar aus dem 2003er-Standard.
audacia schrieb:
ISO/IEC 14882 schrieb:
§21.3.4 basic_string element access
`const_reference operator[](size_type pos) const;reference operator[](size_type pos);
Returns: Ifpos < size(), returnsdata()[pos]. Otherwise, ifpos == size(), the const version returnscharT()` . Otherwise, the behavior is undefined.
-
stimmt

hab ich ma wieder nur die hälfte gelesen...
dann fällt mir jetzt gerade auch keine möglichkeit ein - wirst du wohl recht haben ^^
Imho istreturns data()[pos]eigtl schon die Garantie dafür, dass intern ein vector genommen wird...
aber in nem Jahr ist das dann hoffentlich nicht mehr so ^^bb
-
audacia schrieb:
Das ist mir schon klar. Aber der Rückgabewert des Indexoperators muß praktisch
*const_cast <CharT*> (data () + n)sein - wie von der Definition des Index-Operators gefordert -, ...Nein, diese Forderung wird vom Standard nicht gestellt. Es muss der gleiche Wert sein, aber nicht das gleiche Objekt. Du überinterpretierst die Aussage des Standards. Es kann ja auch nicht das gleiche Objekt sein, denn sonst würde diese Definition gegen die const correctness verstossen.
Was hier gefordert wird ist eigentlich das folgende:
std::string mystring = "hello"; assert(mystring.data()[2] == mystring[2]);Aber ganz sicher nicht dies:
assert(&mystring.data()[2] == &mystring[2]); // -> ist undefiniertGrüssli
-
Dravere schrieb:
audacia schrieb:
Das ist mir schon klar. Aber der Rückgabewert des Indexoperators muß praktisch
*const_cast <CharT*> (data () + n)sein - wie von der Definition des Index-Operators gefordert -, ...Nein, diese Forderung wird vom Standard nicht gestellt. Es muss der gleiche Wert sein, aber nicht das gleiche Objekt. Du überinterpretierst die Aussage des Standards. Es kann ja auch nicht das gleiche Objekt sein, denn sonst würde diese Definition gegen die const correctness verstossen.
Du unterintepretierst die Forderung. Daß der Standard den Rückgabewert des Indexoperators - eine non-const-Referenz! - als
data()[n]definiert, ist an sich bereits ungenau. Meine Interpretation ist: derconst_cast<>wurde zugunsten der Klarheit weggelassen; stünde er da, wäre es eindeutig. Deine Interpretation aber zieht sich auf Wertgleichheit zurück, was beim Umgang mit Referenzen IMHO weit hergeholt ist.Ein interessanter Aspekt dabei ist die Tatsache, daß die Definition in den Entwürfen des 1998er-Standards und möglicherweise auch im finalen Standard nicht auf
data()zurückgriff, sondern sich der Iteratoren bediente. Das wird sicherlich nicht ohne Grund geändert worden sein.
-
Und es ist mal wieder soweit, es ist eine Frage der Interpretation. Wieso können die Leute vom Standard eigentlich die Dinge nicht explizit angeben? Scheiss egal, wenn sie sich wiederholen, dafür aber so, dass es klar und verständlich ist. Bei
std::vectorsteht ja auch:The elements of a vector are stored contiguously, meaning that if v is a vector<T, Allocator> where T is some type other than bool, then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size().
Bei
std::basic_stringsteht dies nirgends, deshalb gehe ich davon aus, dass dies nicht der Fall sein muss und bei der Definition überdata()[n]geht es nur um Wertgleichheit. Wenn sie wirklich dasconst_castweggelassen haben, dann ist es ein Fehler im Standard. Wer lässt bitte Genauigkeit im Standard weg?Grüssli
-
audacia schrieb:
Sebastian Pizer schrieb:
Welche Typsicherheit meinst Du denn? Die Sorte von Typsicherheit, die Typfehler schon zur Kompilierzeit abfangen kann oder nur die Sorte, die Laufzeitüberprüfungen einbaut?
Laufzeitüberprüfung. Die Überprüfung zur Übersetzungszeit ist nicht möglich, wenn der Format-String erst zur Laufzeit bestimmt wird (z.B. mit gettext). Für die Fälle, wo es aber möglich ist, gibt es z.B. -Wformat bei GCC.
Funktioniert das auch für Deine selbst geschriebene var-args Funktion? :p
Gruß,
SP
-
Sebastian Pizer schrieb:
audacia schrieb:
Sebastian Pizer schrieb:
Welche Typsicherheit meinst Du denn? Die Sorte von Typsicherheit, die Typfehler schon zur Kompilierzeit abfangen kann oder nur die Sorte, die Laufzeitüberprüfungen einbaut?
Laufzeitüberprüfung. Die Überprüfung zur Übersetzungszeit ist nicht möglich, wenn der Format-String erst zur Laufzeit bestimmt wird (z.B. mit gettext). Für die Fälle, wo es aber möglich ist, gibt es z.B. -Wformat bei GCC.
Funktioniert das auch für Deine selbst geschriebene var-args Funktion? :p
Ja. Erfordert drei oder vier zusätzliche Zeilen neben der Deklaration.
Dravere schrieb:
Wieso können die Leute vom Standard eigentlich die Dinge nicht explizit angeben?
Weil die menschliche Sprache immer Interpretationsfreiheit läßt. In dem konkreten Fall stimme ich zu, das hätte man sehr einfach deutlicher ausdrücken können, aber solange keine formale Grammatik existiert, um die Semantik einer Sprache zu beschreiben - mir ist keine bekannt -, werden derartige Ungenauigkeiten unvermeidlich auftauchen.