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 действительно одинаковы?
Ответы
Ответ 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, вам нужно явно объявить его.