I'm reading C++ Templates: The Complete Guide, chapter 23. Metaprogramming. At the end, it describes the difference in using enumeration values versus static constants in metaprogramming. Consider the following two implementations of calculating Nth power of 3:
Enumeration implementation:
// primary template to compute 3 to the Nth
template<int N>
struct Pow3 {
enum { value = 3 * Pow3<N-1>::value };
};
// full specialization to end the recursion
template<>
struct Pow3<0> {
enum { value = 1 };
};
Static constant implementation:
// primary template to compute 3 to the Nth
template<int N>
struct Pow3 {
static int const value = 3 * Pow3<N-1>::value;
};
// full specialization to end the recursion
template<>
struct Pow3<0> {
static int const value = 1;
};
Right after that it says there is a drawback to the latter version. If we got a function
void foo(int const&); and pass it the result of metaprogram: foo(Pow3<7>::value); the book says:
A compiler must pass the address of Pow3<7>::value, and that forces the compiler to instantiate and allocate the definition for the static member. As a result, the computation is no longer limited to a pure “compile-time” effect. Enumeration values aren’t lvalues (i.e., they don’t have an address). So, when we pass them by reference, no static memory is used. It’s almost exactly as if you passed the computed value as a literal.
I don't understand their explanation at all to be honest. I thought in the static constant version we evaluate the result at compile time, but the actual referencing happen in run-time because we need to pass the adress. But then I don't see much difference in the former case (enum implementation) because we should have temporary materialization there (prvalue -> xvalue conversion) and since temporary objects also have the adress my thinking process fails. Also it says "no static memory is used" which I don't understand as well since static memory should refer to allocation that happen at compile-time.
Could someone explain this whole thing in greater detail?