In C ++ 11 wurde eine sehr praktische Funktion eingeführt, die als Raw-String-Literale bezeichnet wird. Hierbei handelt es sich um Strings ohne Escape-Zeichen. Und anstatt dies zu schreiben:
regex mask("\\t[0-9]+\\.[0-9]+\\t\\\\SUB");
Sie können dies einfach schreiben:
regex mask(R"(\t[0-9]+\.[0-9]+\t\\SUB)");
Ziemlich lesbarer. Beachten Sie jedoch zusätzliche Klammern um die Zeichenfolge, die platziert werden müssen, um ein rohes Zeichenfolgenliteral zu definieren.
Meine Frage ist, warum brauchen wir diese überhaupt? Für mich sieht es ziemlich hässlich und unlogisch aus. Hier sind die Nachteile, die ich sehe:
- Zusätzliche Ausführlichkeit, während die gesamte Funktion verwendet wird, um Literale kompakter zu gestalten
- Schwer zu unterscheiden zwischen dem Körper des Literal und den definierenden Symbolen
Das meine ich mit der harten Unterscheidung:
"good old usual string literal"
^- body inside quotes -^
R"(new strange raw string literal)"
^- body inside parenthesis -^
Und hier ist der Profi:
- Mehr Flexibilität, mehr Zeichen in rohen Zeichenfolgen verfügbar, insbesondere bei Verwendung mit dem Trennzeichen:
"delim( can use "()" here )delim"
Aber hey, wenn Sie mehr Flexibilität benötigen, haben Sie alte, gute, flüchtige String-Literale. Warum hat das Standardkomitee beschlossen, den Inhalt jedes rohen String-Literals mit diesen absolut unnötigen Klammern zu verschmutzen? Was war der Grund dafür? Was sind die Profis, die ich nicht erwähnt habe?
UPD Die Antwort von Kerrek ist großartig, aber leider keine Antwort. Da ich bereits beschrieben habe, dass ich verstehe, wie es funktioniert und welche Vorteile es bietet. Fünf Jahre sind vergangen, seit ich diese Frage gestellt habe, und es gibt immer noch keine Antwort. Und diese Entscheidung frustriert mich immer noch. Man könnte sagen, dass dies Geschmackssache ist, aber ich würde nicht zustimmen. Wie viele Leerzeichen verwenden Sie, wie benennen Sie Ihre Variablen, ist dies SomeFunction()
oder some_function()
- das ist Geschmackssache. Und ich kann wirklich leicht von einem Stil zum anderen wechseln.
Aber das? .. fühlt sich nach so vielen Jahren immer noch unbeholfen und ungeschickt an. Nein, hier geht es nicht um den Geschmack. Hier geht es darum, wie wir alle möglichen Fälle abdecken wollen, egal was passiert. Wir waren dazu verdammt, diese hässlichen Parens jedes Mal zu schreiben, wenn wir einen Windows-spezifischen Pfad, einen regulären Ausdruck oder ein mehrzeiliges String-Literal schreiben müssen. Und wofür? .. Für die seltenen Fälle, in denen wir tatsächlich "
eine Zeichenfolge einfügen müssen? Ich wünschte, ich wäre auf dieser Ausschusssitzung, wo sie beschlossen hätten, dies auf diese Weise zu tun. Und ich wäre stark gegen diese wirklich schlechte Entscheidung. Ich wünsche. Jetzt sind wir zum Scheitern verurteilt.
Vielen Dank, dass Sie so weit gelesen haben. Jetzt geht es mir etwas besser.
UPD2 Hier sind meine alternativen Vorschläge, von denen ich denke, dass beide VIEL besser wären als die bestehenden.
Vorschlag 1. Inspiriert von Python. String-Literale mit dreifachen Anführungszeichen können nicht unterstützt werden:R"""Here is a string literal with any content, except for triple quotes, which you don't actually use that often."""
Vorschlag 2. Inspiriert vom gesunden Menschenverstand. Unterstützt alle möglichen String-Literale, genau wie das aktuelle : R"delim"content of string"delim"
. Mit leerem Trennzeichen : R""Looks better, doesn't it?""
. Leere Rohzeichenfolge : R""""
. Rohzeichenfolge mit doppelten Anführungszeichen : R"#"Here are double quotes: "", thanks"#"
.
Probleme mit diesen Vorschlägen?
quelle
R";-](R"(this is a basic raw string literal as text inside a more complex one)");-]"
"
eine rohe Zeichenfolge benötigen, " selten "sind, ist wahrscheinlich Teil des Problems. Es ist nicht so, dass es" keine Antwort "gibt. Es gibt eine Antwort; Sie stimmen einfach nicht damit überein . Wenn Ihre Definition dessen, was eine "Antwort" darstellt, "etwas ist, das mich überzeugt, meine Meinung dazu zu ändern", dann ist Ihre Frage zu eigensinnig. Die Begründung wurde geliefert, Ihre Zustimmung dazu ist nicht erforderlich.Antworten:
Wie die andere Antwort erklärt, muss das Anführungszeichen zusätzlich hinzugefügt werden, um die Mehrdeutigkeit beim Parsen in Fällen zu vermeiden, in denen
"
oder)"
oder tatsächlich eine Abschlusssequenz in der Zeichenfolge selbst erscheint.Was die Syntaxauswahl betrifft, stimme ich zu, dass die Syntaxauswahl suboptimal ist , aber im Allgemeinen in Ordnung ist (man könnte sich vorstellen: "Dinge könnten schlimmer sein", lol). Ich denke, es ist ein guter Kompromiss zwischen einfacher Verwendung und einfacher Analyse.
Es gibt in der Tat ein Problem damit - "Anführungszeichen, die Sie eigentlich nicht so oft verwenden". Zum einen ist die Idee der rohen Strings darzustellen rohe Strings, also genau so , wie sie in einer Textdatei, ohne erscheinen würde jegliche Änderungen an der Zeichenfolge, unabhängig von den String Inhalt. Zweitens sollte die Syntax allgemein sein, dh ohne Variationen wie "fast rohe Zeichenfolge" usw. hinzuzufügen.
Wie würden Sie ein Zitat mit dieser Syntax schreiben? Zwei Zitate? Hinweis - Dies sind sehr häufige Fälle, insbesondere wenn sich Ihr Code mit Zeichenfolgen und Parsing befasst.
Nun, dieser könnte ein besserer Kandidat sein. Eine Sache - ein häufiger Fall (und ich glaube, es war ein motivierender Fall für akzeptierte Syntax) - ist, dass das doppelte Anführungszeichen selbst sehr häufig ist und rohe Zeichenfolgen für diese Fälle nützlich sein sollten.
Mal sehen, normale String-Syntax:
s1 = "\""; s2 = "\"quoted string\"";
Ihre Syntax zB mit "x" als Delim:
s1 = R"x"""x"; s2 = R"x""quoted string""x";
Akzeptierte Syntax:
s1 = R"(")"; s2 = R"("quoted string")";
Ja, ich stimme zu, dass die Klammern einen störenden visuellen Effekt hervorrufen. Ich vermute also, dass die Autoren der Syntax nach der Idee waren, dass das zusätzliche "Delim" in diesem Fall selten benötigt wird, da es
)"
nicht sehr oft in einem String vorkommt. Aber OTOH, nachgestellte / führende / isolierte Anführungszeichen sind ziemlich häufig, so dass beispielsweise Ihre vorgeschlagene Syntax (# 2) einigedelim
häufiger erfordern würde , was wiederum eine häufigere Änderung vonR""..""
von erfordern würdeR"delim"..."delim"
. Hoffe du kommst auf die Idee.Könnte die Syntax besser sein? Ich persönlich würde eine noch einfachere Variante der Syntax bevorzugen:
Rdelim"string contents"delim;
Mit den obigen Beispielen:
s1 = Rx"""x; s2 = Rx""quoted string""x;
Um jedoch korrekt zu funktionieren (wenn dies in der aktuellen Grammatik überhaupt möglich ist), würde diese Variante eine Beschränkung des Zeichensatzes für das
delim
Teil erfordern, beispielsweise nur auf Buchstaben / Ziffern (aufgrund vorhandener Operatoren), und möglicherweise einige weitere Einschränkungen für das ursprüngliche Zeichen auf Vermeiden Sie Konflikte mit einer möglichen zukünftigen Grammatik.Ich glaube also, dass eine bessere Wahl hätte getroffen werden können, obwohl in diesem Fall nichts wesentlich Besseres getan werden kann.
quelle
Mit den Klammern können Sie ein benutzerdefiniertes Trennzeichen angeben:
R"foo(Hello World)foo" // the string "Hello World"
In Ihrem Beispiel und in der typischen Verwendung ist das Trennzeichen einfach leer, sodass die Rohzeichenfolge von den Sequenzen
R"(
und eingeschlossen wird)"
.Das Zulassen beliebiger Trennzeichen ist eine Entwurfsentscheidung, die den Wunsch widerspiegelt, eine vollständige Lösung ohne seltsame Einschränkungen oder Randfälle bereitzustellen. Sie können eine beliebige Zeichenfolge auswählen , die in Ihrer Zeichenfolge nicht als Trennzeichen vorkommt.
Ohne dies wären Sie in Schwierigkeiten, wenn die Zeichenfolge selbst etwas enthält
"
(wenn Sie nurR"..."
als Roh-String-Syntax wollten ) oder)"
(wenn das Trennzeichen leer ist). Beides sind sehr häufige und häufige Zeichenfolgen, insbesondere in regulären Ausdrücken. Daher wäre es unglaublich ärgerlich, wenn die Entscheidung, ob Sie eine Rohzeichenfolge verwenden oder nicht, vom spezifischen Inhalt Ihrer Zeichenfolge abhängt.Denken Sie daran, dass es in der rohen Zeichenfolge keinen anderen Escape-Mechanismus gibt. Das Beste, was Sie sonst tun könnten, wäre, Teile des Zeichenfolgenliteral zu verketten, was sehr unpraktisch wäre. Wenn Sie ein benutzerdefiniertes Trennzeichen zulassen, müssen Sie lediglich einmal eine ungewöhnliche Zeichenfolge auswählen und diese möglicherweise in sehr seltenen Fällen ändern, wenn Sie eine zukünftige Bearbeitung vornehmen.
Um es noch einmal zu betonen, ist sogar das leere Trennzeichen bereits nützlich, da Sie mit der
R"(...)"
Syntax nackte Anführungszeichen in Ihre Zeichenfolge einfügen können. Das allein ist ein ziemlicher Gewinn.quelle
)foo
es nicht in Ihrer Zeichenfolge erscheint, einschließlich der Klammer. Die d-char-Sequenz selbst kann tatsächlich willkürlich erscheinen.)foo
kann auch innerhalb der Zeichenfolge erscheinen,)foo"
kann aber nicht.R"foo(Hello World )foo)foo"
ist äquivalent zu"Hello World )foo"
.