是否可以使用有条件选择的字符串文字初始化字符数组?

Rei*_*ica 15 c++ string-literals language-lawyer

我知道char用字符串文字初始化数组是完全可能的:

char arr[] = "foo";
Run Code Online (Sandbox Code Playgroud)

C++ 11 8.5.2/1这样说:

char阵列(是否平原char,signed charunsigned char),char16_t阵列,char32_t阵列或 wchar_t阵列可通过一个窄字符文字,初始化char16_t字符串文字,char32_t字符串文字或宽字符串文字,分别或通过适当类型的字符串文字括在括号内.字符串文字值的连续字符初始化数组的元素....

但是,你可以在条件表达式中使用两个字符串文字吗?例如这样:

char arr[] = MY_BOOLEAN_MACRO() ? "foo" : "bar";
Run Code Online (Sandbox Code Playgroud)

(MY_BOOLEAN_MACRO()扩展为a 10).

C++ 11 5.16(条件运算符)的相关部分如下:

1 ...第一个表达式在上下文中转换为bool(第4条).它被评估,如果是true,则条件表达式的结果是第二个表达式的值,否则是第三个表达式的值....

4如果第二个和第三个操作数是相同值类别的glvalues并且具有相同的类型,则结果属于该类型和值类别,如果第二个或第三个操作数是位字段,则它是位字段,或者如果两者都是位字段.

请注意,文字的长度相同,因此它们都是类型的左值const char[4].

GCC one ideone接受该构造.但是从阅读标准来看,我根本不确定它是否合法.有没有人有更好的洞察力?

Sha*_*our 10

另一方面clang,不接受这样的代码(看到它直播),我相信这clang是正确的(MSVC也拒绝这个代码).

文字串是通过在段语法定义2.14.5:

string-literal:
    encoding-prefixopt" s-char-sequenceopt"
    encoding-prefixoptR raw-string
Run Code Online (Sandbox Code Playgroud)

本节的第一段说(强调我的):

字符串文字由双引号括起的字符序列(如2.14.3中所定义) ,可选地以R,u8,u8R,u,uR,U,UR,L或LR为前缀,如"......"中所示. ,R"(...)",u8"......",u8R" (...) ",u"...",uR" 〜(...)〜",U"......" ,UR"zzz(...)zzz",L"......"或LR"(...)"

并进一步说明了一个狭窄的字符串文字的类型是:

"n const char数组",

以及:

有静态存储时间

但是一个"n const char数组",静态存储持续时间不是字符串文字,因为它不符合语法,也不适合段落1.

gcc如果我们使用非常量表达式,我们可以使它失败(请参见实时):

bool x = true ;
char arr[] = x ? "foo" : "bar";
Run Code Online (Sandbox Code Playgroud)

这意味着它可能是一个扩展,但它不符合要求,因为它不会在严格的一致性模式下产生警告,即使用-std=c++11 -pedantic.来自1.4 [intro.compliance]部分:

[...]根据本国际标准,需要实施来诊断使用此类扩展的程序.但是,这样做之后,他们就可以编译和执行这样的程序.

  • 同意,8.5.2/1似乎很清楚,它是*string literal*而不是*某个表达式,它计算为字符串文字*.(即使您将三元运算符视为在此情况下对字符串文字进行求值). (3认同)