There are similar questions about, but none I've found that directly answer this question.
I want to implement a constexpr function like this:
constexpr int Foo(int x) {
static const int table[128] = { 3, 1, 4, 1, 5, ..., 99 };
return (0 <= x && x < 128) ? table[x] : 42;
}
I'm wary of making the table function-static as shown because the compiler might add expensive checks to make initialization of the table thread safe (slowing each call), and those checks might make the optimizer less likely to inline this otherwise trivial function.
So thought I'd move the table to namespace static, defining it in one .cpp file, while the function itself remains defined in a header so that it can be inlined.
constexpr int Foo(int x) {
extern constexpr int table[];
return (0 <= x && x < 128) ? table[x] : 42;
}
The compiler complains that I can't declare table inside a constexpr function. So then I tried:
extern constexpr int table[];
constexpr int Foo(int x) {
return (0 <= x && x < 128) ? table[x] : 42;
}
That's not allowed because you can't just declare something constexpr, you have to define it. But if I define the table in a header file, I'll violate the one-definition rule, right?
constexpr int table[128] = { 3, 1, 4, 1, 5, ..., 99 };
constexpr int Foo(int x) {
return (0 <= x && x < 128) ? table[x] : 42;
}
I know Foo doesn't violate ODR, because constexpr implies inline for function definitions. The compiler accepts this and seems to do the right thing, but I know compilers aren't required to issue a diagnostic for ODR violations.
Q1: In this last iteration, is table an ODR violation?
Q2: If not, is there a way to prevent table from being visible to every translation unit that includes this header?
ints due to constant initialization. - ildjarnconstexprimpliesconstimpliesstatic, so yes, it's an ODR violation. In C++17 it can be markedinlineto resolve that. - ildjarn