S
steve.lorimer
I'm looking for a pre-processor command that will allow me to resolve
const
strings into const char literals at compile time.
Looking at the code below, I can take 5 characters and create a const
uint64_t value at compile time.
I can then create a switch statement that has these const values as
the
various cases.
Since each case resolves to an integer constant value at compile
time,
this switch statement is valid.
const uint64_t val1 = (static_cast<uint64_t>('S') << 32) | S
(static_cast<uint64_t>('T') << 24) | T
(static_cast<uint64_t>('A') << 16) | A
(static_cast<uint64_t>('R') << 8) | R
(static_cast<uint64_t>('T')); T
const char c1 = 'S', c2 = 'T', c3 = 'O', c4 = 'P';
const uint64_t val2 = (static_cast<uint64_t>(c1) << 32) | S
(static_cast<uint64_t>(c2) << 24) | T
(static_cast<uint64_t>(c3) << 16) | O
(static_cast<uint64_t>(c4) << 8) | P
(static_cast<uint64_t>(0));
uint64_t input = 0;
switch (input)
{
case val1: printf("input=val1\n"); break;
case val2: printf("input=val2\n"); break;
default: break;
}
//--------------------------------------------------------------------------
Now I attempt to repeat the above code, but instead of using literal
character
values, I use a const string literal.
gcc returns the following error:
error: case label does not reduce to an integer constant
So I guess the compiler is not able to resolve the index into the char
array at compile time.
const char* const str1 = "START";
const uint64_t val1 = (static_cast<uint64_t>(str1[0]) << 32) | S
(static_cast<uint64_t>(str1[1]) << 24) | T
(static_cast<uint64_t>(str1[2]) << 16) | A
(static_cast<uint64_t>(str1[3]) << 8) | R
(static_cast<uint64_t>(str1[4])); T
const char* const str2 = "STOP";
const uint64_t val2 = (static_cast<uint64_t>(str2[0]) << 32) | S
(static_cast<uint64_t>(str2[1]) << 24) | T
(static_cast<uint64_t>(str2[2]) << 16) | O
(static_cast<uint64_t>(str2[3]) << 8) | P
(static_cast<uint64_t>(str2[4]));
uint64_t input = 0;
switch (input)
{
case val1: printf("input=val1\n"); break;
case val2: printf("input=val2\n"); break;
default: break;
}
//--------------------------------------------------------------------------
What I actually have is a text file containing many unique input
strings,
each a maximum of 5 characters long.
Each of these input strings has a corresponding name and a value that
it maps to. I'd like to be able to create a switch statement with a
case for each of the
possible input strings which returns the associated value.
At run-time, I can create a uint64_t value from any 5 character input
string and run the value through my case statement to get a return
value. Obviously performance wise this is far better than:
if (strncmp(...))
return ...
else
if (strncmp(...))
return ...
else
ad infinitum
Please see my example data below:
<< input_values.txt >>
MACRO1(DO_START, "START", enum_val_start)
MACRO1(DO_STOP, "STOP", enum_val_stop)
// create const values
#undef MACRO1
#define MACRO1(NAME, INPUT, VALUE) \
const uint64_t val_##NAME = (static_cast<uint64_t>(INPUT[0])
<< 32) | \
(static_cast<uint64_t>(INPUT[1])
<< 24) | \
(static_cast<uint64_t>(INPUT[2])
<< 16) | \
(static_cast<uint64_t>(INPUT[3])
<< 8) | \
(static_cast<uint64_t>(INPUT[4]));
#include "input_values.txt"
// create switch statement containing above const values
#undef MACRO1
#define MACRO1(NAME, INPUT, VALUE) \
case val_##NAME: return VALUE;
switch (val)
{
#include "input_value.txt"
default: break;
}
//--------------------------------------------------------------------------
const
strings into const char literals at compile time.
Looking at the code below, I can take 5 characters and create a const
uint64_t value at compile time.
I can then create a switch statement that has these const values as
the
various cases.
Since each case resolves to an integer constant value at compile
time,
this switch statement is valid.
const uint64_t val1 = (static_cast<uint64_t>('S') << 32) | S
(static_cast<uint64_t>('T') << 24) | T
(static_cast<uint64_t>('A') << 16) | A
(static_cast<uint64_t>('R') << 8) | R
(static_cast<uint64_t>('T')); T
const char c1 = 'S', c2 = 'T', c3 = 'O', c4 = 'P';
const uint64_t val2 = (static_cast<uint64_t>(c1) << 32) | S
(static_cast<uint64_t>(c2) << 24) | T
(static_cast<uint64_t>(c3) << 16) | O
(static_cast<uint64_t>(c4) << 8) | P
(static_cast<uint64_t>(0));
uint64_t input = 0;
switch (input)
{
case val1: printf("input=val1\n"); break;
case val2: printf("input=val2\n"); break;
default: break;
}
//--------------------------------------------------------------------------
Now I attempt to repeat the above code, but instead of using literal
character
values, I use a const string literal.
gcc returns the following error:
error: case label does not reduce to an integer constant
So I guess the compiler is not able to resolve the index into the char
array at compile time.
const char* const str1 = "START";
const uint64_t val1 = (static_cast<uint64_t>(str1[0]) << 32) | S
(static_cast<uint64_t>(str1[1]) << 24) | T
(static_cast<uint64_t>(str1[2]) << 16) | A
(static_cast<uint64_t>(str1[3]) << 8) | R
(static_cast<uint64_t>(str1[4])); T
const char* const str2 = "STOP";
const uint64_t val2 = (static_cast<uint64_t>(str2[0]) << 32) | S
(static_cast<uint64_t>(str2[1]) << 24) | T
(static_cast<uint64_t>(str2[2]) << 16) | O
(static_cast<uint64_t>(str2[3]) << 8) | P
(static_cast<uint64_t>(str2[4]));
uint64_t input = 0;
switch (input)
{
case val1: printf("input=val1\n"); break;
case val2: printf("input=val2\n"); break;
default: break;
}
//--------------------------------------------------------------------------
What I actually have is a text file containing many unique input
strings,
each a maximum of 5 characters long.
Each of these input strings has a corresponding name and a value that
it maps to. I'd like to be able to create a switch statement with a
case for each of the
possible input strings which returns the associated value.
At run-time, I can create a uint64_t value from any 5 character input
string and run the value through my case statement to get a return
value. Obviously performance wise this is far better than:
if (strncmp(...))
return ...
else
if (strncmp(...))
return ...
else
ad infinitum
Please see my example data below:
<< input_values.txt >>
MACRO1(DO_START, "START", enum_val_start)
MACRO1(DO_STOP, "STOP", enum_val_stop)
// create const values
#undef MACRO1
#define MACRO1(NAME, INPUT, VALUE) \
const uint64_t val_##NAME = (static_cast<uint64_t>(INPUT[0])
<< 32) | \
(static_cast<uint64_t>(INPUT[1])
<< 24) | \
(static_cast<uint64_t>(INPUT[2])
<< 16) | \
(static_cast<uint64_t>(INPUT[3])
<< 8) | \
(static_cast<uint64_t>(INPUT[4]));
#include "input_values.txt"
// create switch statement containing above const values
#undef MACRO1
#define MACRO1(NAME, INPUT, VALUE) \
case val_##NAME: return VALUE;
switch (val)
{
#include "input_value.txt"
default: break;
}
//--------------------------------------------------------------------------