2016-01-14 9 views
4

Вслед за этим вопросом Having a constexpr static string gives a linker errorDifferent поведение наблюдается с переменной constexpr авто/углеродно массива

В вопросе, этот код не удалось скомпилировать:

#include <iostream> 

struct Test { static constexpr char text[] = "Text"; }; 

int main() 
{ 
    std::cout << Test::text << std::endl; // error: undefined reference to `Test::text' 
} 

От комментария, этот код может составить:

#include <iostream> 

struct Test { static constexpr auto text = "Text"; }; 

int main() 
{ 
    std::cout << Test::text << std::endl; 
} 

Мой вопрос почему auto версия работает, но массив char версии Безразлично» т?

Не могли бы вы указать заявление в стандарте, разрешающее вторую версию и запрещающее первое?

Я взглянул на Strange behavior with constexpr static member variable, но, похоже, это другой вопрос.

+1

Это тот же самый вопрос и тот же принятый ответ действительно: http://stackoverflow.com/a/28534978/113662, то есть обе версии плохо сформированы, но компилятор не обязан их отклонять и выбирает принять один из них –

+1

@TadeuszKopec Нет, последний не плохо сформирован. – Columbo

+0

@TadeuszKopec Я пропустил ответ Саху, который является дополнением к принятому ответу. В ответе Саху упоминался буквальный тип. И, я неправильно понял, что текст будет выводиться char [] вместо char * – Danh

ответ

8

Объявление статического элемента данных в классе никогда не является определением.
Разница между примерами заключается в том, что только один требует определения text.

auto версия выводит char const*, поэтому text допускается только при преобразовании lvalue-to-rval и не используется odr. Напротив, первый код эффективно пропускает адрес text, используя его, т. Е. Требует определения.

+0

Да, ключ 'text' выводится' char const * 'вместо' char [] '. Я неправильно понял этот момент. – Danh

+0

Не является ли 'const char *' адресом? Я смущен. – Lingxi

+0

@Lingxi Нет, 'const char *' - тип указателя. Объект этого типа указателя, переданный соответствующему 'operator <<' overload, представляет адрес первого 'char' в' text'. – Columbo

2
struct Test { static constexpr auto text = "Text"; }; 

решает

struct Test { static constexpr const char * text = "Text"; }; 

Таким образом, второе выражение является constexpr значение указателя не является массивом.