Подтвердить что ты не робот

Constexpr const vs constexpr переменные?

Кажется очевидным, что constexpr подразумевает const и, следовательно, обычно видно:

constexpr int foo = 42; // no const here

Однако, если вы пишете:

constexpr char *const str = "foo";

Затем GCC вызовет "предупреждение: устаревшее преобразование из строковой константы в" char * ", если передан флаг Wwrite-string.

Запись:

constexpr const char *const str = "foo";

решает проблему.

Значит, constexpr const и constexpr действительно одинаковы?

4b9b3361

Ответ 1

Проблема заключается в том, что в объявлении переменной constexpr всегда применяется const -ness к объявленному объекту; const, с другой стороны, может применяться к другому типу, в зависимости от места размещения.

Таким образом,

constexpr const int i = 3;
constexpr int i = 3;

эквивалентны;

constexpr char* p = nullptr;
constexpr char* const p = nullptr;

эквивалентны; оба делают p a const указатель на char.

constexpr const char* p = nullptr;
constexpr const char* const p = nullptr;

эквивалентны. constexpr делает указатель p a const. const в const char * делает p точкой const char.

Ответ 2

Сообщение об ошибке, которое вы видите, не имеет никакого отношения к ключевому слову constexpr.

Строковый литерал типа "foo", как в:

somefunction("foo");

Тип этого строкового литерала const char *. Следующее утверждение:

char *const str = "foo";

Это пытается присвоить значение const char * значению char *. Результирующее значение char * не изменяет, константу, но к тому времени уже произошла ошибка: попытка конвертировать a const char * в char *.

Ключевое слово constexpr в вашем примере - это просто отвлечение внимания и не влияет на ошибку.

Ответ 3

Нет. Сказать, что они то же самое означает, что нет времени, чтобы не использовать const, было бы справедливо без создания функционально идентичного кода для версии const.

Я считаю это полезным при создании безопасных синглетонов. Я не изучил это полностью и ожидаю, что существуют другие допустимые применения для не const constprpr.

В качестве примера здесь приведен код, который требует не const constprpr:

Начните с глобального определения переменной:

int global_int_;

И теперь мы можем создать функцию constexpr, которая возвращает ссылку на нее:

constexpr int& get_global()
{
    return global_int_;
}

Теперь мы можем использовать эту ссылку где-то еще:

int main()
{
    constexpr int& i{ get_global() };
    // do stuff with i
    return 0;
}

Теперь мы можем использовать i как неконстантный int. Если подразумевалось const, это было бы невозможно.

Поскольку не const constexpr действительно, если вы используете constexpr, который должен быть const, вам нужно явно объявить его.