2015-03-25 1 views
21

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

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

constexpr const char foo[] = "blee"; 

(К сожалению, клиент ноября 2013 Technology Preview не позволяет Visual Studio для поддержки этого: https://stackoverflow.com/a/29255013/2642059)

Но даже с 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 

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

Как отметил этот вопрос может частично ответить на это: Is it possible to use std::string in a constexpr? но это не касается, почему std::string не может быть буквальным, который является основой вопроса.

+0

К кому это может относиться, моя заинтересованность в этом была вызвана ответами на [этот вопрос] (http://stackoverflow.com/q/29166578/2642059). –

+0

@juhist А, я не знаю, как я пропустил это, когда искал. Итак, ответ заключается в том, что 'std :: string' не является литералом? Почему это так? Похоже, было бы просто сделать 'const std :: string' литералом. –

+2

Я думаю, что причина дана в другом ответе: потому что «std :: basic_string» имеет нетривиальный деструктор. – juhist

ответ

26

Существует предложение для constexpr строки: Compile-Time String: std::string_literal и он говорит:

The purpose of std::string_literal , like std::string , is to provide a convenience utility for working with text. Unlike std::string , an instantiation of std::string_literal is a literal type and so can be used at compile­time. That is, it may be the type of an constexpr object, and it may be the type of a parameter, return value or local variable of a constexpr function

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

Так почему бы не просто сделать std::string буквального типа?

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

This would require a massive core language change to make something like dynamic memory available at compile­-time, or to make something like VLA/ARB and permit them in literal types. Given the violently negative reaction of Rapperswil Evolution to not only N4025 (Classes of Runtime Size), but anything that vaguely resembles VLA/ARBs, we can expect this not to happen any time soon, so this idea is a non­starter.

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

Почему constexpr не может быть применена к STD :: строки, но может в массив полукокса

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

A constexpr specifier used in an object declaration declares the object as const . Such an object shall have literal type and shall be initialized. If it is initialized by a constructor call, that call shall be a constant expression (5.19). […]

и из раздела 3.9[основной.Типы]:

A type is a literal type if it is:

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

  • a scalar type; or
  • an array of literal type

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

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

a class type (Clause 9) that has all of the following properties:

  • it has a trivial destructor,
  • every constructor call and full-expression in the brace-or-equal-initializers for non-static data members (if any) is a constant expression (5.19),
  • it is an aggregate type (8.5.1) or has at least one constexpr constructor or constructor template that is not a copy or move constructor, and
  • all of its non- static data members and base classes are of literal types.

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

+1

@downvoter, пожалуйста, объясните, какие-либо технические ошибки, я пропустил очко? –

+1

@downvoter Я тоже хотел бы, чтобы этот downvote был удален, так как я чувствую, что это умело отвечает на вопрос, который я задаю. Если есть причина для downvote, я, конечно, хотел бы увидеть комментарий, объясняющий почему. –

+1

Мне часто задавалось вопросом, можно ли перегрузить конструктор 'std :: string' таким образом, чтобы для случаев, когда он вызывается с строковым литералом (или другим применимым постоянным выражением), достаточно коротким для включения SSO, 'constexpr' будет вскакивать. – 5gon12eder

5

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

+2

Вы говорите, что это единственная причина, по которой 'std :: string' не является литеральным типом, существует несколько критериев для класса. –