C ++ 11的原始字符串文字R“(...)”中括号的基本原理是什么?

时间:2013-09-29 08:34:01

标签: c++ c++11 standards string-literals

C ++ 11中引入了一个非常方便的特性,称为原始字符串文字,它是没有转义字符的字符串。而不是写这个:

  regex mask("\\t[0-9]+\\.[0-9]+\\t\\\\SUB");

你可以简单地写一下:

  regex mask(R"(\t[0-9]+\.[0-9]+\t\\SUB)");

更具可读性。但是,请注意字符串周围的额外括号,以定义原始字符串文字。

我的问题是,为什么我们甚至需要这些?对我来说,它看起来很丑陋和不合逻辑。以下是我看到的缺点:

  • 额外的详细程度,而整个功能用于使文字更紧凑
  • 难以区分文字的主体和定义的符号

这就是我难以区分的意思:

"good old usual string literal"
 ^-    body inside quotes   -^

R"(new strange raw string literal)"
   ^- body inside parenthesis  -^

这是专业人士:

  • 更灵活,原始字符串中可用的字符更多,尤其是与分隔符一起使用时:"delim( can use "()" here )delim"

但是,嘿,如果你需要更多的灵活性,你有旧的好的可逃避字符串文字。为什么标准委员会决定用这些绝对不必要的括号来污染每个原始字符串文字的内容?那背后的理由是什么?我没有提到的专业是什么?

UPD Kerrek的答案很棒,但不幸的是,这不是一个答案。因为我已经描述过我理解它是如何工作的,它给了什么好处。自从我提出这个问题五年过去了,仍然没有答案。我仍然对这个决定感到沮丧。可以说这是一个品味问题,但我不同意。您使用了多少个空格,如何命名变量,这是SomeFunction()还是some_function() - 这是品味的问题。我可以轻松地从一种风格切换到另一种风格。

但是这个?经过这么多年后仍然感到尴尬和笨拙。不,这不是味道。这是关于我们如何想要涵盖所有可能的情况,无论如何。每当我们需要编写特定于Windows的路径,或正则表达式或多行字符串文字时,我们注定要编写这些丑陋的parens。为了什么?..对于那些我们确实需要将"放入字符串的极少数情况?我希望我参加委员会会议,他们决定这样做。我强烈反对这个非常糟糕的决定。我希望。现在我们注定要失败。

感谢您阅读此内容。现在我感觉好多了。

UPD2 以下是我的备选提案,我认为两者都比现有提案好很多。

提案1.灵感来自python。不能使用三引号支持字符串文字:R"""Here is a string literal with any content, except for triple quotes, which you don't actually use that often."""

建议2.受常识启发。支持所有可能的字符串文字,就像当前的字符串文字一样:R"delim"content of string"delim"。使用空分隔符:R""Looks better, doesn't it?""。空原始字符串:R""""。带双引号的原始字符串:R"#"Here are double quotes: "", thanks"#"

这些提案有任何问题吗?

2 个答案:

答案 0 :(得分:95)

括号的目的是允许您指定自定义分隔符:

R"foo(Hello World)foo"   // the string "Hello World"

在您的示例中,在典型使用中,分隔符只是空的,因此原始字符串由序列R"()"括起来。

允许任意分隔符是一种设计决策,它反映了在没有奇怪限制或边缘情况的情况下提供完整解决方案的愿望。您可以选择任何字符串中不会出现在字符串中的字符串作为分隔符。

如果没有这个,如果字符串本身包含"(如果您只是想要R"..."作为原始字符串语法)或)"(如果是分隔符),则会遇到麻烦是空的)。这两者都是非常常见和频繁的字符序列,特别是在正则表达式中,因此如果您决定是否使用原始字符串取决于字符串的特定内容,那将会非常烦人。

请记住,在原始字符串中没有其他的转义机制,所以你能做的最好的事情就是连接字符串文字,这是非常不切实际的。通过允许自定义分隔符,您需要做的只是选择一个不寻常的字符序列,并且可能在极少数情况下修改它,以便您将来进行编辑。

但是再次强调,即使空分隔符已经很有用,因为R"(...)"语法允许您在字符串中放置裸引号。这本身就是一个很大的收获。

答案 1 :(得分:5)

正如另一个答案所解释的那样,在")"的情况下,或者在字符串本身中可能出现的任何关闭序列的情况下,引号之外还必须有其他内容以避免语法歧义。

对于语法选择,我同意语法选择是 suboptimal ,但是总体来说还可以(您可能会想到:“情况可能会更糟”,大声笑)。我认为这是用法简单和解析简单之间的良好折衷。

  

建议1 。受python启发。无法使用来支持字符串文字   三引号:
  R“”“您除三引号外的任何内容   实际上并不经常使用。“”“

这确实存在一个问题-“引号,您实际上并不经常使用”。 首先,原始字符串的基本思想是表示 raw 字符串,即与在文本文件中显示的字符串完全一样,而无需对字符串进行任何修改,而与字符串无关内容。其次,语法应通用,即不要添加“几乎原始字符串”等变体。

如何用这种语法写一个引号?两个引号?注意-这是非常常见的情况,尤其是当您的代码正在处理字符串和解析时。

  

提案2
  字符串“ delim”的R“ delim”内容。
  R“”看起来更好,不是吗?“”。
  R“#”在这里是双引号:“”,谢谢“#”。

嗯,这可能是一个更好的候选人。但是,有一件事-一个常见的情况(我相信这是接受语法的一个有力的例子),是双引号字符本身是非常,在这些情况下,原始字符串应该派上用场。

所以,让我们看一下正常的字符串语法:

s1 = "\"";
s2 = "\"quoted string\"";

您的语法,例如使用“ x”作为delim:

s1 = R"x"""x";
s2 = R"x""quoted string""x";

可接受的语法:

s1 = R"(")";
s2 = R"("quoted string")";

是的,我同意括号会带来一些令人讨厌的视觉效果。因此,我怀疑语法的作者是在这样的想法之后的,即几乎不需要在这种情况下使用附加的“ delim”,因为)"很少出现在字符串中。但是OTOH经常使用尾随/前导/隔离引号,因此您建议的语法(#2)会需要更多delim,而这反过来又需要将其从R""..""更改为R"delim"..."delim"。希望你能明白。

语法会更好吗?我个人更希望使用一种更简单的语法:

Rdelim"string contents"delim;

使用以上示例:

s1 = Rx"""x; 
s2 = Rx""quoted string""x;

无论如何正常工作(如果在当前语法中完全可行),此变体将需要限制delim部分的字符集,仅说字母/数字(由于现有的运算符),也许对初始字符的一些进一步限制,以避免与将来可能出现的语法冲突。
因此,我相信可以做出更好的选择,尽管在这种情况下,没有什么可以做得更好。