Reputation: 376
I want to define a constexpr function strip_string
which allows:
const char*
of the final size as a constant so the binary will contain the reduced string and not the original string.The purpose is to keep a readable string in the source and have the shortest string in the binary.
I'm using Visual Studio C++ 2017.
As an example:
I want that in my source (and only in my source, not in my binary!):
R"SQL("
CREATE TABLE IF NOT EXISTS "MyTable" (
"ID" INTEGER NOT NULL,
"Field1" TEXT NOT NULL,
"Field2" TEXT,
PRIMARY KEY("ID")
)
)SQL"
And only that in my binary (and no original string!):
CREATE TABLE IF NOT EXISTS "MyTable" ( "ID" INTEGER NOT NULL, "Field1" TEXT NOT NULL, "Field2" TEXT, PRIMARY KEY("ID"))
And here the last attempt of code which still shows using constexpr before each functions is not enough to turn them into real constants:
#include <cstddef>
#include <utility>
#include <iostream>
constexpr bool is_whitespace(char c) {
return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v';
}
template<std::size_t N>
constexpr std::size_t calculate_final_length(const char (&input)[N]) {
std::size_t start = 0;
std::size_t end = N - 1;
while (start < end && is_whitespace(input[start])) {
++start;
}
while (end > start && is_whitespace(input[end - 1])) {
--end;
}
std::size_t trimmed_length = end - start;
std::size_t final_length = 0;
bool in_whitespace = false;
for (std::size_t i = 0; i < trimmed_length; ++i) {
char c = input[start + i];
if (is_whitespace(c)) {
if (!in_whitespace) {
++final_length;
in_whitespace = true;
}
} else {
++final_length;
in_whitespace = false;
}
}
return final_length;
}
template<std::size_t N>
constexpr auto strip_string(const char (&input)[N]) {
constexpr std::size_t final_length = calculate_final_length(input); // Fails to turn it into constant
char result[final_length + 1] = {};
std::size_t out_index = 0;
bool in_whitespace = false;
// Calculer les indices de début et de fin après suppression des blancs
std::size_t start = 0;
std::size_t end = N - 1;
while (start < end && is_whitespace(input[start])) {
++start;
}
while (end > start && is_whitespace(input[end - 1])) {
--end;
}
// Calculer la longueur après trim
std::size_t trimmed_length = end - start;
// Remplir le tableau résultant avec les caractères traités
for (std::size_t i = 0; i < trimmed_length; ++i) {
char c = input[start + i];
if (is_whitespace(c)) {
if (!in_whitespace) {
result[out_index++] = ' ';
in_whitespace = true;
}
} else {
result[out_index++] = c;
in_whitespace = false;
}
}
result[out_index] = '\0';
return result;
}
constexpr const char raw_string[] = ;
constexpr auto test = strip_string(
R"( This is a RAW string test )");
int main() {
std::cout << test;
std::cout << '\n';
return 0;
}
As the code was never able to compile, I couldn't test it further.
Upvotes: -1
Views: 210
Reputation: 4247
The error means: An expression declared as const or constexpr didn't evaluate to a constant at compile time.
Check the Compiler Error C2131 sammple:
struct test
{
static const int array_size; // To fix, init array_size here.
int size_array[array_size]; // C2131
};
const int test::array_size = 42;
Even the example link in the comments uses const N.
template<std::size_t N>
struct ct_string {
char bytes[N];
char result[final_length + 1] = {};
using non-const variables does not meet the requirements.
Upvotes: -1