2015-03-04 4 views
14

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

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 действительно то же самое?

ответ

24

Проблема заключается в том, что в декларации переменной constexpr всегда применяет свойство const к объявленному объекту; 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; 

эквивалентны. constexprp a const Указатель. const в const char * составляет p. Указывает на const char.

1

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

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

somefunction("foo"); 

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

char *const str = "foo"; 

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

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

+0

В то время как верно, я думаю, что ОР прав, он _ought_ должен иметь отношение к ошибке. 'constexpr' и' constexpr const' должны быть одинаковыми. –

+1

Проблема заключается в преобразовании const char * в char *. Является ли результирующее значение константой или constexpr, не является фактором. Ошибка уже произошла по этой точке. Такая же ошибка будет происходить только с простым символом char * foo = "bar". –

+2

Тип '' foo '' is 'const char [4]'. –

-1

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

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

В качестве примера, вот код, который требует неконстантную constexpr:

Start с глобальным определением переменной:

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, это было бы невозможно.

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

+2

Это полная красная селедка. C++ 14 constexpr-not-implicitly-const предназначен для функций-членов. –

+0

@ T.C. Я представил пример non-const constexpr без функции-члена, поэтому я не уверен, что вы имеете в виду. –

+1

Это не имеет ничего общего с изменением C++ 14. Точно так же, как с указателями, 'constexpr' применяется к самой ссылке (которая является no-op, поскольку ссылки не могут быть изменены в любом случае), а не объект, о котором идет речь. –

Смежные вопросы