Is it possible to initialise a character array with a conditionally selected string literal?

為{幸葍}努か 提交于 2019-12-03 05:22:41

On the other hand clang does not accept such code (see it live) and I believe clang is correct on this (MSVC also rejects this code ).

A string literal is defined by the grammar in section 2.14.5:

string-literal:
    encoding-prefixopt" s-char-sequenceopt"
    encoding-prefixoptR raw-string

and the first paragraph from this section says (emphasis mine):

A string literal is a sequence of characters (as defined in 2.14.3) surrounded by double quotes, optionally prefixed by R, u8, u8R, u, uR, U, UR, L, or LR, as in "...", R"(...)", u8"...", u8R"(...)", u"...", uR"˜(...)˜", U"...", UR"zzz(...)zzz", L"...", or LR"(...)", respectively

and it further says that the type of a narrow string literal is:

“array of n const char”,

as well as:

has static storage duration

but an “array of n const char”, with static storage duration is not a string literal since it does not fit the grammar nor does it fit paragraph 1.

We can make this fail on gcc if we use a non-constant expression (see it live):

bool x = true ;
char arr[] = x ? "foo" : "bar";

which means it is probably an extension, but it is non-conforming since it does not produce a warning in strict conformance mode i.e. using -std=c++11 -pedantic. From section 1.4 [intro.compliance]:

[...]Implementations are required to diagnose programs that use such extensions that are ill-formed according to this International Standard. Having done so, however, they can compile and execute such programs.

inetknght

This works in GCC in C++11 or newer because the literals you're providing are deterministic during compile time (eg, they are constexpr). Since the compiler can figure out which one is true, it is allowed to figure out which one to use.

To remove the constexpr ability, try something like this:

#include <iostream>
#include <cstdlib>

int main() {
    bool _bool = rand();
    char arr[] = (_bool) ? "asdf" : "ffff";

    std::cout << arr << std::endl;
}

GCC then errors out with:

g++ test.cpp -std=c++11
test.cpp: In function ‘int main()’:
test.cpp:6:34: error: initializer fails to determine size of ‘arr’
  char arr[] = (_bool) ? "asdf" : "ffff";
                                  ^
test.cpp:6:34: error: array must be initialized with a brace-enclosed initializer

I don't know the standard's text definition well enough to know where or why this is valid, but I feel that it is valid.

For further reading on constexpr and how it can impact compilability, see the answer by @ShafikYaghmour in another question.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!