I have this piece of generated code that maps ints to ints, whose core is a simple table. In pre C++17, it used to look like this:
int convert (int v)
{
static const int table[] = { 3, 2, 6, 1, 7, 1, 6, 8 };
if (0 <= v && v < sizeof table / sizeof table[0])
return table[v];
else
return -1;
}
with C++17, I would like use constexpr. I expected that adding constexpr
to the function signature would suffice, but I have to remove the static
of the table, which makes my implementation more complex for apparently no good reason. Not too mention that table
in non constexpr context will probably be on the stack, so I guess I should replace static
by constexpr
.
G++ 8 reports:
/tmp/foo.cc: In function 'constexpr int convert(int)':
/tmp/foo.cc:14:26: error: 'table' declared 'static' in 'constexpr' function
static const int table[] = { 3, 2, 6, 1, 7, 1, 6, 8 };
^
and Clang++ 7:
/tmp/foo.cc:14:20: error: static variable not permitted in a constexpr function
static const int table[] = { 3, 2, 6, 1, 7, 1, 6, 8 };
^
1 error generated.
Since I want this piece of code to work with all the C++ standards (and do the right thing in each case), I think I have to write this (yeah, macros, that's not the question):
#if 201703L <= __cplusplus
# define CONSTEXPR constexpr
# define STATIC_ASSERT static_assert
# define STATIC_OR_CONSTEXPR constexpr
#else
# include <cassert>
# define CONSTEXPR
# define STATIC_ASSERT assert
# define STATIC_OR_CONSTEXPR static
#endif
CONSTEXPR int convert (int v)
{
STATIC_OR_CONSTEXPR const int table[] = { 3, 2, 6, 1, 7, 1, 6, 8 };
if (0 <= v && v < sizeof table / sizeof table[0])
return table[v];
else
return -1;
}
int main()
{
STATIC_ASSERT(convert(-42) == -1);
STATIC_ASSERT(convert(2) == 6);
STATIC_ASSERT(convert(7) == 8);
STATIC_ASSERT(convert(8) == -1);
}
So:
what motivates the interdiction to have static-storage variables in constexpr functions?
is there a cleaner alternative I might have missed? Sure, I can pull
table
out ofconvert
, but I would like to avoid that.does the standard guarantee that const arrays in constexpr functions in non-constexpr contexts will be in static storage instead of the stack?