Constexpr const char * vs constexpr const char []

"Первая попытка" не компилируется, пока выполняется вторая. Зачем? Какая разница?

Первая попытка:

#include <iostream>

int main()
{
    constexpr const char text2[] = "hello";
    constexpr const char * b = &text2[4];  // error: '& text2[4]' is not a constant expression
    std::cout << b << std::endl;
}

Вторая попытка:

#include <iostream>
int main()
{
constexpr const char * text1 = "hello";
constexpr const char * a = &text1[4];
std::cout << a << std::endl;

return 0;
}

Я компилирую с (g++ версия 4.9.2)

g++ -std=c++11 -o main *.cpp

который дает следующую ошибку

main.cpp: In function 'int main()':
main.cpp:7:40: error: '& text2[4]' is not a constant expression constexpr const char * b = &text2[4];  // error: '& text2[4]' is not a constant expression  

Ответы

Ответ 1

Из стандартного раздела проекта С++ 11 5.19 [expr.const] мы можем видеть выражение адресное постоянное выражение (выделение мое Гонг вперед):

[...] выражение константы основного значения prvalue типа указателя, который оценивает адрес объекта с помощью статический срок хранения, адрес функции или нулевой значение указателя или константное выражение типа prvalue типа станд:: nullptr_t.

В вашем первом случае, хотя "hello" является строковым литералом, который имеет статическую продолжительность хранения. Он копируется в массив text2, который не имеет статической продолжительности хранения.

Пока во втором случае text1 является указателем на строковый литерал, который имеет статическую продолжительность хранения.

Измените свой первый пример, чтобы сделать text2 static (посмотреть его в прямом эфире):

constexpr char static text2[] = "hello";
               ^^^^^^

мы больше не получаем ошибку.

Мы можем видеть, что строковый литерал имеет статическую длительность хранения из раздела 2.14.5 [lex.string]:

Также указываются обычные строковые литералы и строковые литералы UTF-8 как узкие строковые литералы. Узкий строковый литерал имеет тип "массив" of n const char ", где n - размер строки, как определено ниже, и имеет статическую продолжительность хранения (3.7).