Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a string literal be subscripted in a constant expression?

This is valid, because a constexpr expression is allowed to take the value of "a glvalue of literal type that refers to a non-volatile object defined with constexpr, or that refers to a sub-object of such an object" (§5.19/2):

constexpr char str[] = "hello, world";
constexpr char e = str[1];

However, it would seem that string literals do not fit this description:

constexpr char e = "hello, world"[1]; // error: literal is not constexpr

2.14.5/8 describes the type of string literals:

Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration.

It would seem that an object of this type could be indexed, if only it were temporary and not of static storage duration (5.19/2, right after the above snippet):

[constexpr allows lvalue-to-rvalue conversion of] … a glvalue of literal type that refers to a non-volatile temporary object whose lifetime has not ended, initialized with a constant expression

This is particularly odd since taking the lvalue of a temporary object is usually "cheating." I suppose this rule applies to function arguments of reference type, such as in

constexpr char get_1( char const (&str)[ 6 ] )
    { return str[ 1 ]; }

constexpr char i = get_1( { 'y', 'i', 'k', 'e', 's', '\0' } ); // OK
constexpr char e = get_1( "hello" ); // error: string literal not temporary

For what it's worth, GCC 4.7 accepts get_1( "hello" ), but rejects "hello"[1] because "the value of ‘._0’ is not usable in a constant expression"… yet "hello"[1] is acceptable as a case label or an array bound.

I'm splitting some Standardese hairs here… is the analysis correct, and was there some design intent for this feature?

EDIT: Oh… there is some motivation for this. It seems that this sort of expression is the only way to use a lookup table in the preprocessor. For example, this introduces a block of code which is ignored unless SOME_INTEGER_FLAG is 1 or 5, and causes a diagnostic if greater than 6:

#if "\0\1\0\0\0\1"[ SOME_INTEGER_FLAG ]

This construct would be new to C++11.

like image 225
Potatoswatter Avatar asked Sep 15 '11 00:09

Potatoswatter


People also ask

Are string literals constant?

String constants, also known as string literals, are a special type of constants which store fixed sequences of characters. A string literal is a sequence of any number of characters surrounded by double quotes: "This is a string."

Is it possible to modify a string literal?

The behavior is undefined if a program attempts to modify any portion of a string literal. Modifying a string literal frequently results in an access violation because string literals are typically stored in read-only memory.

Is a string literal an expression?

STR objects represent strings (See Type). String literal expressions begin and end with double quote marks. The characters making up the string are specified in this construct from left to right.

What is a character string literal constant?

String Literals. A String Literal, also known as a string constant or constant string, is a string of characters enclosed in double quotes, such as "To err is human - To really foul things up requires a computer." String literals are stored in C as an array of chars, terminted by a null byte.


1 Answers

The intent is that this works and the paragraphs that state when an lvalue to rvalue conversion is valid will be amended with a note that states that an lvalue that refers to a subobject of a string literal is a constant integer object initialized with a constant expression (which is described as one of the allowed cases) in a post-C++11 draft.

Your comment about the use within the preprocessor looks interesting but I'm unsure whether that is intended to work. I hear about this the first time at all.

like image 73
Johannes Schaub - litb Avatar answered Oct 04 '22 17:10

Johannes Schaub - litb