CSC/ECE 517 Spring 2013/ch1 1h jc: Difference between revisions
Line 10: | Line 10: | ||
===Pre-generate static data at compile time=== | ===Pre-generate static data at compile time=== | ||
One common use of metaprogramming in statically typed languages is to write programs that will pre-generate tables of data for use at runtime. | One common use of metaprogramming in statically typed languages is to write programs that will pre-generate tables of data for use at runtime. | ||
A practicable approach to pre-generate static data at compile time in C++ is template metaprogramming. Template metaprograms consist of class templates operating on numbers and/or types as data. Algorithms are expressed using template recursion as a looping construct and class template specialization as a conditional construct. Template recursion involves the direct or indirect use of a class template in the construction of its own member type or member constant. | A practicable approach to pre-generate static data at compile time in C++ is template metaprogramming. Template metaprograms consist of class templates operating on numbers and/or types as data. Algorithms are expressed using template recursion as a looping construct and class template specialization as a conditional construct. Template recursion involves the direct or indirect use of a class template in the construction of its own member type or member constant. |
Revision as of 21:31, 17 February 2013
Metaprogramming in statically typed languages
Introduction
What is metaprogramming
Metaprogramming in statically typed languages
Implementation
Exposing the internals of the compiler as an API
Program transformation system
Metaprogramming using Scheme
Common Uses
Pre-generate static data at compile time
One common use of metaprogramming in statically typed languages is to write programs that will pre-generate tables of data for use at runtime.
A practicable approach to pre-generate static data at compile time in C++ is template metaprogramming. Template metaprograms consist of class templates operating on numbers and/or types as data. Algorithms are expressed using template recursion as a looping construct and class template specialization as a conditional construct. Template recursion involves the direct or indirect use of a class template in the construction of its own member type or member constant.
Here is an example of a class template which computes the factorial of a natural number:
template<int n> struct Factorial { enum { RET = Factorial<n-1>::RET * n }; }; //the following template specialization terminates the recursion template<> struct Factorial<0> { enum { RET = 1 }; };
We can use this class template as follows:
void main() { cout << Factorial<7>::RET << endl; //prints 5040 }
The important point about this program is that Factorial<7> is instantiated at compile time. During the instantiation, the compiler also determines the value of Factorial<7>::RET. Thus, the code generated for this main() program by the C++ compiler is the same as the code generated for the following main():
void main() { cout << 5040 << endl; //prints 5040 }
We can regard Factorial<> as a function which is evaluated at compile time. This particular function takes one number as its parameter and returns another in its RET member (RET is an abbreviation for RETURN; we use this name to mimic the return statement in a programming language). It is important to note that we are dealing with a shift of intentionality here: The job of the compiler is to do type inference and type construction which involves computation. We use the fact that the compiler does computation and, by encoding data as types, we can actually use (or abuse) the compiler as a processor for interpreting metaprograms. Thus, we refer to functions such as Factorial<> as metafunctions. Factorial<> is a metafunction since, at compilation time, it computes constant data of a program which has not been generated yet.