Это действительно, поскольку экспрессия CONSTEXPR
разрешено принимать значение «Tlvalue буквального типа, которое относится к на ненулительную объект, определенный с constexpr, или это относится к подзерцезнику такого объекта "(§5.19 / 2):
constexpr char str[] = "hello, world";
constexpr char e = str[1];
Тем не менее, казалось бы, что строковые литералы не соответствуют этому описанию:
constexpr char e = "hello, world"[1]; // error: literal is not constexpr
2.14,5 / 8 описывает тип строковых литералов:
Обычные строковые литералы и строковые литералы UTF-8 также называют узкими строковыми литералами. Узкая строка литерала имеет тип «массив N Const Char», где n - это размер строки, как определено ниже, и имеет статический длительность хранения.
Кажутся, что объект этого типа может быть проиндексирован, если только это временно, а не с длительностью статического хранения (5,19 / 2, сразу после вышеуказанного фрагмента):
[
[
CONSTEXPR
позволяет преобразовать преобразование Lvalue-rvalue] ... воспоминание буквального типа, который относится к нелетующему временному объекту, срок службы которого не закончился, инициализировался с постоянным выражением
Особенно странно с момента принятия временного объекта, обычно «обмана». Я полагаю, что это правило относится к функционированию аргументов репорционального типа, например, в
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
для того, что он стоит, GCC 4.7 принимает Get_1 («Hello»)
, но отклоняет «Привет» [1]
, потому что «Значение» ._0 'не используется в постоянном выражении «... И все же « Hello »[1]
является , приемлемым в качестве метки регистрации или границ массива.
Я разделяю несколько стандартных волосков здесь ... это анализ правильным, и был ли какой-то дизайн намерения для этой функции?
Редактировать: О ... есть некоторая мотивация для этого. Похоже, что такое выражение является единственным способом использования таблицы поиска в препроцессоре. Например, это представляет собой блок кода, который игнорируется, если que_integer_flag
не составляет 1 или 5, а приводит к диагностике, если он превышает 6:
#if "\0\1\0\0\0\1"[ SOME_INTEGER_FLAG ]
Эта конструкция была бы новой для C ++ 11.