I'm currently trying to use constexpr
to define some input identification stuff:
struct RangeParams {
string legacyId;
string fullname;
string shortname;
float min = -1;
float baseline = 0;
float max = 1;
float defaultValue = 0;
};
...
inline constexpr RangeParams curve1 = { "some_id", "my_name", ...};
Unfortunately, I get an error for the constexpr line saying
Constexpr variable cannot have non-literal type 'const RangeParams'
So, I dug into it to figure out what part of this is non-literal, and string
was the culprit.
std::cout << std::is_literal_type<float>::value; // output: 1
std::cout << std::is_literal_type<string>::value; // output: 0
Finding this has highlighted an important fact for me which is that my understanding of literal-types is rather flawed. For the most part, I'd simply thought of them as being the basics (numbers, strings, booleans, structs made of those things).
So why would a simple string not be a literal type? What's the gotcha here?
Also, how can I get around this? I'm trying to make a global out of my RangeParams and the most modern answer to this question (Defining global constant in C++) appears not be working.
std::string
is not a literal. const char[]
is. The gotcha is that a std::string
is a container of a dynamic size. No, you can't get around this and still use std::string
. std::string
is unusable in constexpr context.
You might want to replace std::string
with const char*
in your code:
struct RangeParams {
const char* legacyId;
const char* fullname;
const char* shortname;
float min = -1;
float baseline = 0;
float max = 1;
float defaultValue = 0;
};
It's not exactly the same, but given the lack of context, it's hard to justify what did you exactly need the std::string
for, thus it's uncertain that a const char*
will be a suitable alternative.
EDIT: A short example should help to understand the misconception. What is the type of 0
?. It's an int
. What's the type of 'a'
? It's a char
. What's the type of "abc"
? It's not std::string
, it's const char[4]
!