I probably shouldn't answer the question of template metaprogramming this late. But, here I go.
Firstly, constexpr is not implemented in Visual Studio 2012. If you want to develop for Windows, forget about it. I know this sucks; I hate Microsoft for not including it.
With this you can say that there are many things that you can declare constant, but they are not "permanent" in terms of "you can work with them during compilation." For example:
const int foo[5] = { 2, 5, 1, 9, 4 }; const int bar = foo[foo[2]];
Do you think you could read this at compile time, right? Nope. But you can do it constexpr.
constexpr int foo[5] = { 2, 5, 1, 9, 4 }; constexpr int bar = foo[foo[2]];
Constexpr is really good at optimizing "continuous distribution." This means that if you have an X variable declared at compile time based on some condition (possibly metaprogramming), if it is constexpr, then the compiler knows that it can “safely” use it when performing optimization, for example, when deleting such instructions like a = (X * y); and replace them with a = 0; if X is evaluated to 0 (and other conditions are satisfied).
Obviously, this is great, because for many mathematical functions, constant propagation can give you easy (use) premature optimization.
Their main use, in addition to quite esoteric things (for example, allowing me to write a bytecode interpreter in the compiler is much simpler), is to be able to create "functions" or classes that can be called and used both during compilation and during fulfillment.
Basically, they just fill a hole in C ++ 03 and help optimize the compiler.
So which of your 3s is "better"?
2 can be called at run time, while others can only be called at compile time. It is very nice.
There is a bit more. Wikipedia gives you a very general summary of “constexpr allows this,” but metaprogramming a template can be tricky. Constexpr greatly facilitates its parts. I'm sorry that I did not have a clear example for you, except, say, from an array.
A good mathematical example, I suppose, would be if you wanted to implement a custom complex class of numbers. It would be an order of magnitude more difficult to code this with just metaprogramming the template and without constexpr.
So when should you not use constexpr? Honestly, constexpr is basically "const, except MORE CONST". Usually, you can use it wherever you use const, with a few warnings, for example, how, when called at run time, a function will act unstable if its input is not const.
Um. All right for now. I was too overdoing to say more. Hope I was helpful, feel free to if I don’t, and I will remove it.