zamar wrote:
(1) PvNode is a template parameter, so we want this code to be generated only for PV nodes. Speed optimization trick.
Not to be pedantic, but I would like to spend few words on this because templates are heavily used in SF and because it seems is one of the few engines with available sources that use this powerful C++ feature.
Just to be very very basic and up to the point, when you see something like
Code: Select all
v = my_func<SomeParameter>(a1, a2, a3);
it means that inside the function my_func() the parameter SomeParameter is evaluated at compile time, IOW suppose SomeParameter has boolean type, as is the case with PvNode in search().
A boolean type can have 2 values, 'true' and 'false'. What the compiler does is to create
two copies of my_func(), the first that we can call my_func<true>() is a function built from my_func() where all the instances of SomeParameter are substituted at
compile time by 'true', the second my_func<false>() is a function where all the instances of SomeParameter are substituted at compile time by 'false'.
Then, after this step, the compilers compiles the two obtained functions indipendently using the usual C/C++ rules.
So when in the code you see something like:
Code: Select all
void my_func<SomeParameter>(....) {
.....
if (SomeParameter && another_condition)
{
do_something();
}
.....
}
what happens is that the compiler creates two functions:
Code: Select all
void my_func<true>(....) {
if (another_condition)
{
do_something();
}
}
void my_func<false>(....) {
// This will be removed during next compilations steps
// because is unreachable code.
if (false && another_condition)
{
do_something();
}
}
And the two functions will then be compiled indipendently.
So the bottom line is that templates are a facility to generate a family of different functions starting from a single and shared...ehm..template
This greatly reduce source code redundancy with zero speed penalty overhead.