17.8 Afternotes
As mentioned earlier, the earliest documented example of a metaprogram was by Erwin Unruh, then representing Siemens on the C++ standardization committee. He noted the computational completeness of the template instantiation process and demonstrated his point by developing the first metaprogram. He used the Metaware compiler and coaxed it into issuing error messages that would contain successive prime numbers. Here is the code that was circulated at a C++ committee meeting in 1994 (modified so that it now compiles on standard conforming compilers)3:
// meta/unruh.cpp // prime number computation by Erwin Unruh template <int p, int i> class is_prime { public: enum { prim = (p==2) || (p%i) && is_prime<(i>2?p:0),i-1>::prim }; }; template<> class is_prime<0,0> { public: enum {prim=1}; }; template<> class is_prime<0,1> { public: enum {prim=1}; }; template <int i> class D { public: D(void*); }; template <int i> class Prime_print { // primary template for loop to print prime numbers public: Prime_print<i-1> a; enum { prim = is_prime<i,i-1>::prim }; void f() { D<i> d = prim ? 1 : 0; a.f(); } }; template<> class Prime_print<1> { // full specialization to end the loop public: enum {prim=0}; void f() { D<1> d = prim ? 1 : 0; }; }; #ifndef LAST #define LAST 18 #endif int main() { Prime_print<LAST> a; a.f(); }
If you compile this program, the compiler will print error messages when in Prime_print::f(), the initialization of d fails. This happens when the initial value is 1. because there is only a constructor for void*, and only 0 has a valid conversion to void*. For example, on one compiler we get (among other messages) the following errors:
unruh.cpp:36: conversion from &39;int&39; to non-scalar type &39;D<17>&39; requested unruh.cpp:36: conversion from &39;int&39; to non-scalar type &39;D<13>&39; requested unruh.cpp:36: conversion from &39;int&39; to non-scalar type &39;D<11>&39; requested unruh.cpp:36: conversion from &39;int&39; to non-scalar type &39;D<7>&39; requested unruh.cpp:36: conversion from &39;int&39; to non-scalar type &39;D<5>&39; requested unruh.cpp:36: conversion from &39;int&39; to non-scalar type &39;D<3>&39; requested unruh.cpp:36: conversion from &39;int&39; to non-scalar type &39;D<2>&39; requested
The concept of C++ template metaprogramming as a serious programming tool was first made popular (and somewhat formalized) by Todd Veldhuizen in his paper Using C++ Template Metaprograms (see [VeldhuizenMeta95]). Todds work on Blitz++ (a numeric array library for C++, see [Blitz++]) also introduced many refinements and extensions to the metaprogramming (and to expression template techniques, introduced in the next chapter).