Both last nicht as well as this morning, as soon as souldog mentioned that interesting comment about template programming, my respect for this topic was reawakened.
In fact, it is really a very rich topic. The samples below show some of the interesting cases which can arise. Take a look.
// Probably data
static const int n = 3;
const int m = 5;
// I do not know?
static const double dc = ::sqrt(0.3);
// Template metaprogram
template <int N> struct factorial
value = factorial<N-1>::value * N
template <> struct factorial<0>
value = 1
// Use of the template metaprogram.
static volatile int four_factorial = static_cast<int>(factorial<4>::value);
int main(int argc, char* argv)
// Probably a local register.
const double d = ::sin(0.1);
// Maybe a register, maybe not.
// Maybe considered bad style?
register const int rn = 12;
volatile const int vc = 34;
You're gonna go blind staring into that box all day.
The only difference between the const with static and the one without is a scoping one, and that is something the compiler can sort out. For your integral ones it may well optimise and treat them like enums.
Even for one like
const long double pi = 3.1415926535897932384626433832795;
the compiler may well substitute a literal everywhere pi is used.
We already know that using string literals will lead to undefined behaviour if you try modifying them.
For scoping purposes it is probably best to use namespaces to avoid naming clashes (better than using static with your const).