Can C-Strings or std::string
s be created as constexpr
or must they be created at run-time?
With gcc 4.9.2 I can do this:
constexpr const char foo[] = "blee";
(Sadly the November 2013 Customer Technology Preview does not allow Visual Studio to support this: https://stackoverflow.com/a/29255013/2642059)
But even with gcc 4.9.2 I cannot do this:
constexpr const std::string foo = "blee";
I get the error:
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
But I would like more clarification on why a std::string
is not a literal. That is to say: Why must a string be constructed at run-time?
As pointed out this question can partially be answered by this: Is it possible to use std::string in a constexpr? but it does not touch on the why std::string
can not be a literal which is core to the question.
There is a proposal for a constexpr string: Compile-Time String: std::string_literal and it says:
The purpose of
std::string_literal
, likestd::string
, is to provide a convenience utility for working with text. Unlikestd::string
, an instantiation ofstd::string_literal
is a literal type and so can be used at compiletime. That is, it may be the type of anconstexpr
object, and it may be the type of a parameter, return value or local variable of aconstexpr
function
which also confirms that indeed std::string
is not a literal type.
So why not just make std::string
a literal type?
We get a hint why from the proposal above why this not possible:
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 nonstarter.
std::string
requires dynamic memory which is not available at compile time.
Why constexpr can not be applied to std::string but can to array of char
constexpr
applied to an object shall be applied to a literal type which does not apply to std::string
but applies to an array of const char
. From the draft C++11 standard section 7.1.5
[dcl.constexpr] (emphasis mine going forward):
A
constexpr
specifier used in an object declaration declares the object asconst
. 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). […]
and from section 3.9
[basic.types]:
A type is a literal type if it is:
and includes:
- a scalar type; or
- an array of literal type
Arithmetic types are scalar types and include char, which covers the array of const char
and for classes:
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
does not meet that criteria.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With