Protoman wrote:
So, how does the compiler execute the metaprogram?
Well. If *you* were the compiler. What would *you* need to
do in order to create an executable program.
(Actually: A surprisingly large number of so called 'clever'
programming is just an adoption of what people do in real
life. So if you direct your thinking into 'What would I do
if all I have is paper and pencil?' is surprisingly often
an excellent tool in understanding what is going on.)
The compiler comes to compiling:
const complex<long double> phi= Fib<32>::val/Fib<31>::val;
This is a declaration of a complex<double> variable called phi.
The variable is initialized with the value of
Fib<32>::val/Fib<31>::val
For this the compiler needs to know
Fib<32>::val
and Fib<31>::val
Fib<32> is the instantiation of a template. Thus the compiler
looks up the Fib template and substitutes 32 for N
template <long N>
class Fib
{
public:
static const long double val=Fib<N-2>::val+Fib<N-1>::val;
};
becomes
class Fib
{
public:
static const long double val=Fib<30>::val+Fib<31>::val;
};
In order to make this compilable the compiler has to come up with
the initial value for val. For this it has to evaluate the initialization
part:
Fib<30>::val+Fib<31>::val
Again: The compiler is looking for an instantiation of Fib<30> and since
there is none it creates one, substituting 30 for N
class Fib
{
public:
static const long double val=Fib<28>::val+Fib<29>::val;
};
Part of compiling that one, makes the compiler look for an instatiation
of Fib<28>. Since there is none, the compiler creates one, using 28 for N
class Fib
{
public:
static const long double val=Fib<26>::val+Fib<27>::val;
};
And so on, and so on.
Finally the compiler will have the request to intialize one of the
generated classes with:
class Fib
{
public:
static const long double val=Fib<1>::val+Fib<2>::val;
};
Looking for Fib<1> the compiler figures out, that the programmer specified
that one:
template<>
class Fib<1>
{
public:
static const long double val=1;
};
so it doesn't need to create one on its own. Same for Fib<2>.
Since those 2 classes are 'complete' the compiler now can use
them to continue working on
class Fib
{
public:
static const long double val=Fib<1>::val+Fib<2>::val;
};
(which was the template instatiation for Fib<3>).
Fib<1>::val is known, it equals 1.
Fib<2>::val is known, it equals 1
Thus the initialization value for Fib<3>::val thus must be 2
Having this value, the compiler can continue on finishing
Fib<4> and so on, and so on, until finally Fib<32>::val can
be calculated by the compiler.
Now the whole story starts again for Fib<31>.
If both values Fib<32>::val and Fib<31>::val are known to the
copmiler, it can easily calculate Fib<32>::val / Fib<31>::val
and assign that value to phi.
However why one would want to do all of that with complex numbers
is bejond my imagination.
--
Karl Heinz Buchegger
kb******@gascad.at