Where to put compile-time-constant arrays?
Say I have an array storing the first 10 primes, like this:
const int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
This is all very fine and simple as long as I have 1 .cpp file. However, if I have multiple .cpp files I don't really know where to put this array.
An obvious solution would be this:
// prime开发者_开发百科s.h:
extern const int primes[10];
// primes.cpp:
extern const int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
However, the problem with this is that the primes array is no longer a compile time constant. Say x.cpp wants to do some heavy calculations involving primes[k], with k a compile time constant, it would have to do an actual memory look-up. I don't like that.
So where do I put this array so that:
- It's only once in the binary (not once per .cpp file)
- array[SOME_CONSTANT] is also a compile-time constant
Edit
how about this?
inline int prime(int i) {
static const int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
return primes[i];
}
PS: Even the "obvious solution" above took me quite some time to write. Apparently const variables have internal linking by default, so I had to add "extern" to the primes.cpp file to make it work.
I think this should work (now updated after Migi's testing revealed a flaw):
template <bool dummy>
struct primes_lut
{
static const int values[];
};
template<bool dummy>
const int primes_lut<dummy>::values[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };
static auto& primes = primes_lut<true>::values;
(There is no problem in C++ that cannot be solved by use of more templates.)
Another approach:
struct primes_lut { int values[10]; };
inline const primes_lut& primes_lut_provider(void)
{
static const primes_lut values = { {2, 3, 5, 7, 11, 13, 17, 19, 23, 29} };
return values;
}
static const int (&primes)[10] = primes_lut_provider().values;
Finally, none of these tricks are necessary with a modern linker than implements constant folding.
You could use enum inside a header. Enums are guaranteed to be compile time constants and (unless you use C++0X enum class) implicitly convert to integers.
static const int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
in a header file. This may lead to a bigger executable (each source file will have its own copy of the array) but I think the same problem applies for the currently accepted answer.
精彩评论