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

Почему строка должна быть построена во время выполнения?

Можно ли создать C-строки или std::string как constexpr или они должны быть созданы во время выполнения?

С gcc 4.9.2 я могу это сделать:

constexpr const char foo[] = "blee";

(К сожалению, ноябрьский показ технологии Customer Technology Preview не позволяет Visual Studio поддерживать это: qaru.site/info/133608/...)

Но даже с gcc 4.9.2 я не могу этого сделать:

constexpr const std::string foo = "blee";

Я получаю сообщение об ошибке:

error: the type 'const string {aka const std::basic_string<char>}' of constexpr variable 'foo' 
       is not literal

 constexpr const std::string foo = "blee";
                                   ^
note: 'std::basic_string<char>' is not literal because:
     class basic_string
           ^
note:   'std::basic_string<char>' has a non-trivial destructor

Но я хотел бы получить больше разъяснений по поводу того, почему std::string не является литералом. То есть: Почему строка должна быть построена во время выполнения?

Как уже указывалось, на этот вопрос можно частично ответить следующим образом: Можно ли использовать std::string в constexpr?, но он не затрагивает причины std::string не может быть литералом, который является ключевым для вопроса.

4b9b3361

Ответ 1

Существует предложение для строки constexpr: Строка времени компиляции: std:: string_literal и в ней говорится:

Цель std::string_literal, например std::string, состоит в том, чтобы предоставить удобную утилиту для работы с текстом. В отличие от std::string, экземпляр std::string_literal является литералом типа и поэтому могут использоваться в compiletime. То есть, это может быть тип объекта constexpr, и это может быть тип параметра, возвращаемое значение или локальная переменная функции constexpr

что также подтверждает, что действительно std::string не является литеральным типом.

Итак, почему бы просто не сделать std::string литеральный тип?

Мы получаем подсказку, почему из предложения выше, почему это невозможно:

Это потребует значительного изменения основного языка, чтобы что-то сделать как динамическая память, доступная во время компиляции, или что-то сделать как VLA/ARB, и разрешать их в литеральных типах. Учитывая жестокость отрицательная реакция эволюции Rapperswil на не только N4025 (классы Runtime Size), но все, что смутно напоминает VLA/ARB, мы может ожидать, что это не произойдет в ближайшее время, поэтому эта идея неудачник.

std::string требуется динамическая память, которая недоступна во время компиляции.

Почему constexpr не может быть применен к std::string, но может быть массив из char

constexpr, применяемый к объекту, применяется к типу литерала, который не применяется к std::string, но применяется к массиву const char. Из стандартного раздела проекта С++ 11 7.1.5 [dcl.constexpr] (выделение в будущем):

A constexpr спецификатор, используемый в объявлении объекта, объявляет объект как const. Такой объект должен иметь буквальный тип и должен инициализируется. Если он инициализируется вызовом конструктора, это вызов должен быть постоянным выражением (5.19). [...]

и из раздела 3.9 [basic.types]:

Тип - это буквальный тип, если он:

и включает в себя:

  • скалярный тип; или
  • массив литералов типа

Арифметические типы являются скалярными типами и включают char, который охватывает массив const char

и для классов:

тип класса (раздел 9), который имеет все следующие свойства:

  • имеет тривиальный деструктор,
  • каждый вызов конструктора и полноэкранное выражение в элементарных элементах для нестатических данных (если они есть) является константным выражением (5.19),
  • это тип агрегата (8.5.1) или имеет хотя бы один конструктор конструктора или конструктора constexpr, который не является копией или перемещением конструктор и
  • все элементы данных не static и базовые классы имеют литеральные типы.

std::string не соответствует этим критериям.

Ответ 2

Вы не можете использовать constexpr, потому что std::string не имеет тривиального деструктора. Проверьте требования к cppreference.