mirror of
https://gitlab.com/fbb-git/cppannotations
synced 2024-11-16 07:48:44 +01:00
WIP
git-svn-id: https://cppannotations.svn.sourceforge.net/svnroot/cppannotations/trunk@392 f6dd340e-d3f9-0310-b409-bdd246841980
This commit is contained in:
parent
dd701821d7
commit
be726acf65
3 changed files with 38 additions and 39 deletions
|
@ -22,13 +22,13 @@ sect(Template Meta Programming)
|
|||
lsubsubsect(INTTYPE)(Converting integral types to types)
|
||||
includefile(advancedtemplates/int2type)
|
||||
|
||||
COMMENT(>>>>>>>>>>>>> NEXT <<<<<<<<<<<<<)
|
||||
lsubsect(ALTERNATIVES)(Selecting alternatives using templates)
|
||||
includefile(advancedtemplates/alternatives)
|
||||
|
||||
subsect(Templates: Iterations by Recursion)
|
||||
includefile(advancedtemplates/iterating)
|
||||
|
||||
COMMENT(>>>>>>>>>>>>> NEXT <<<<<<<<<<<<<)
|
||||
lsect(TEMPTEMPPAR)(Template template parameters)
|
||||
includefile(advancedtemplates/templateparam)
|
||||
|
||||
|
|
|
@ -255,9 +255,7 @@ implementations of these overloaded members may then be optimized to the
|
|||
various data types. In programs only one of these alternate functions (the one
|
||||
that is optimized to the actually used data types) will then be instantiated.
|
||||
|
||||
COMMENT(>>>>>>>>>>>>> NEXT <<<<<<<<<<<<<)
|
||||
|
||||
Note that the overloaded tt(add) functions have identical parameter lists
|
||||
as the matching public wrapper function, but add to this parameterlist a
|
||||
specific tt(IntType) type, allowing the compiler to select the appropriate
|
||||
overloaded version, based on the template's non-type selector parameter.
|
||||
The private tt(add) functions define the same parameters as the public
|
||||
tt(add) wrapper function, but add a specific tt(IntType) type, allowing the
|
||||
compiler to select the appropriate overloaded version based on the template's
|
||||
non-type selector parameter.
|
||||
|
|
|
@ -1,27 +1,25 @@
|
|||
Since there are no variables
|
||||
hi(templates: no variables)
|
||||
in template meta programming, there is no way to implement iteration using
|
||||
templates. However, iterations can always be rewritten as recursions, and
|
||||
since recursions em(are) supported by templates iterations can always be
|
||||
rewritten as (tail) recursions.
|
||||
As there are no variables in template meta programming, there is no
|
||||
template equivalent to a tt(for) or tt(while) statement. However, iterations
|
||||
can always be rewritten as recursions. Recursions em(are) supported
|
||||
by templates and so iterations can always be implemented as (tail) recursions.
|
||||
hi(templates: iteration by recursion)
|
||||
|
||||
The principle to follow here is:
|
||||
To implement iterations by (tail) recursion do as follows:
|
||||
itemization(
|
||||
it() Define a specialization implementing the end-condition;
|
||||
it() Define all other steps using recursion.
|
||||
it() Store intermediate values as tt(enum) values.
|
||||
it() define a specialization implementing the end-condition;
|
||||
it() define all other steps using recursion.
|
||||
it() store intermediate values as tt(enum) values.
|
||||
)
|
||||
Since the compiler will select a more specialized implementation over a
|
||||
more generic one, by the time it reaches the final recursion it will stop the
|
||||
recursion since the specialization will not rely on recursion anymore.
|
||||
The compiler selects a more specialized template implementation over a
|
||||
more generic one. By the time the compiler reaches the end-condition the
|
||||
recursion stops since the specialization does not use recursion.
|
||||
|
||||
Most readers will be familiar with the recursive implementation of the
|
||||
mathematical `em(factorial)' operator, indicated by the exclamation mark
|
||||
(tt(!)). Factorial tt(n) (so: tt(n!)) returns the successive products tt(n *
|
||||
(n - 1) * (n - 2) * ... * 1), representing the number of ways tt(n) objects
|
||||
can be permuted. Interestingly, the factorial operator is usually defined by a
|
||||
em(recursive) definition:
|
||||
mathematical `em(factorial)' operator, commonly represented by the exclamation
|
||||
mark (tt(!)). Factorial tt(n) (so: tt(n!)) returns the successive products
|
||||
tt(n * (n - 1) * (n - 2) * ... * 1), representing the number of ways tt(n)
|
||||
objects can be permuted. Interestingly, the factorial operator is itself
|
||||
usually defined by a em(recursive) definition:
|
||||
verb(
|
||||
n! = (n == 0) ?
|
||||
1
|
||||
|
@ -29,10 +27,10 @@ em(recursive) definition:
|
|||
n * (n - 1)!
|
||||
)
|
||||
To compute tt(n!) from a template, a template tt(Factorial) can be defined
|
||||
using a tt(int n) template non-type parameter, and defining a specialization
|
||||
using an tt(int n) template non-type parameter. A specialization is defined
|
||||
for the case tt(n == 0). The generic implementation uses recursion according
|
||||
to the factorial definition. Furthermore, the tt(Factorial) template defines an
|
||||
tt(enum) value `tt(value)' to contain the its factorial value. Here is the
|
||||
to the factorial definition. Furthermore, the tt(Factorial) template defines
|
||||
an tt(enum) value `tt(value)' containing its factorial value. Here is the
|
||||
generic definition:
|
||||
verb(
|
||||
template <int n>
|
||||
|
@ -41,17 +39,19 @@ generic definition:
|
|||
enum { value = n * Factorial<n - 1>::value };
|
||||
};
|
||||
)
|
||||
Note how the expression assigning a value to `tt(value)' uses constant,
|
||||
compiler determinable values: n is provided, and tt(Factorial<n - 1>()) is
|
||||
computed by em(template meta programming), also resulting in a compiler
|
||||
determinable value. Also note the interpretation of tt(Factorial<n - 1>::value):
|
||||
it is the tt(value) defined by the type tt(Factorial<n - 1>); it's em(not),
|
||||
e.g., the value returned by an em(object) of that type. There are no objects
|
||||
here, simply values defined by types.
|
||||
Note how the expression assigning a value to `tt(value)' uses constant
|
||||
values that can be determined by the compiler. The value n is provided, and
|
||||
tt(Factorial<n - 1>) is computed using em(template meta
|
||||
programming). tt(Factorial<n-1>) in turn results in value that can be
|
||||
determined by the compiler (em(viz.)
|
||||
tt(Factorial<n-1>::value)). tt(Factorial<n-1>::value) represents the tt(value)
|
||||
defined by the em(type) tt(Factorial<n - 1>). It is em(not) the value returned
|
||||
by an em(object) of that type. There are no objects here but merely values
|
||||
defined by types.
|
||||
|
||||
To end the resrsion a specialization is required, which will be preferred
|
||||
by the compiler over the generic implementation when its template arguments
|
||||
are present. The specialization can be provided for the value 0:
|
||||
The recursion ends in a specialization. The compiler will select the
|
||||
specialization (provided for the terminating value 0) instead of the generic
|
||||
implementation whenever possible. Here is the specialization's implementation:
|
||||
verb(
|
||||
template <>
|
||||
struct Factorial<0>
|
||||
|
@ -69,7 +69,8 @@ number of permutations of a fixed number of objects. E.g.,
|
|||
}
|
||||
)
|
||||
Once again, tt(Factorial<5>::value) is em(not) evaluated run-time, but
|
||||
compile-time. The above statement is therefore run-time equivalent to:
|
||||
compile-time. The run-time equivalent of the above tt(cout) statement is,
|
||||
therefore:
|
||||
verb(
|
||||
int main()
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue