导言
1994年,C++标准委员会在圣迭哥举行的一次会议期间Erwin Unruh展示了一段可以产生质数的代码。这段代码的特别之处在于质数产生于编译期而非运行期,在编译器产生的一系列错误信息中间夹杂着从2到某个设定值之间的所有质数:
// Prime number computation by Erwin Unruh template <int i> struct D { D(void*); operator int(); };
template <int p, int i> struct is_prime { enum { prim = (p%i) && is_prime<(i > 2 ? p : 0), i -1> :: prim }; };
template < int i > struct Prime_print { Prime_print<i-1> a; enum { prim = is_prime<i, i-1>::prim }; void f() { D<i> d = prim; } };
struct is_prime<0,0> { enum {prim=1}; }; struct is_prime<0,1> { enum {prim=1}; }; struct Prime_print<2> { enum {prim = 1}; void f() { D<2> d = prim; } }; #ifndef LAST #define LAST 10 #endif main () { Prime_print<LAST> a; } |
类模板D只有一个参数为void*的构造器,而只有0才能被合法转换为void*。1994年,Erwin Unruh采用Metaware 编译器编译出错信息如下(以及其它一些信息,简短起见,它们被删除了):
| Type `enum{}′ can′t be converted to txpe `D<2>′ ("primes.cpp",L2/C25). | Type `enum{}′ can′t be converted to txpe `D<3>′ ("primes.cpp",L2/C25). | Type `enum{}′ can′t be converted to txpe `D<5>′ ("primes.cpp",L2/C25). | Type `enum{}′ can′t be converted to txpe `D<7>′ ("primes.cpp",L2/C25). |
如今,上面的代码已经不再是合法的C++程序了。以下是Erwin Unruh亲手给出的修订版,可以在今天符合标准的C++编译器上进行编译:
// Prime number computation by Erwin Unruh
template <int i> struct D { D(void*); operator int(); };
template <int p, int i> struct is_prime { enum { prim = (p==2) || (p%i) && is_prime<(i>2?p:0), i-1> :: prim }; };
template <int i> struct Prime_print { Prime_print<i-1> a; enum { prim = is_prime<i, i-1>::prim }; void f() { D<i> d = prim ? 1 : 0; a.f();} };
template<> struct is_prime<0,0> { enum {prim=1}; }; template<> struct is_prime<0,1> { enum {prim=1}; };
template<> struct Prime_print<1> { enum {prim=0}; void f() { D<1> d = prim ? 1 : 0; }; };
#ifndef LAST #define LAST 18 #endif
main() { Prime_print<LAST> a; a.f(); } |
在GNU C++ (MinGW Special) 3.2中编译这段程序时,编译器将会给出如下出错信息(以及其它一些信息,简短起见,它们被删除了):
Unruh.cpp:12: initializing argument 1 of `D<i>::D(void*) [with int i = 17]' Unruh.cpp:12: initializing argument 1 of `D<i>::D(void*) [with int i = 13]' Unruh.cpp:12: initializing argument 1 of `D<i>::D(void*) [with int i = 11]' Unruh.cpp:12: initializing argument 1 of `D<i>::D(void*) [with int i = 7]' Unruh.cpp:12: initializing argument 1 of `D<i>::D(void*) [with int i = 5]' Unruh.cpp:12: initializing argument 1 of `D<i>::D(void*) [with int i = 3]' Unruh.cpp:12: initializing argument 1 of `D<i>::D(void*) [with int i = 2]' |
这个例子展示了可以利用模板实例化机制于编译期执行一些计算。这种通过模板实例化而执行的特别的编译期计算技术即被称为模板元编程。
顺便说一句,因为编译器的出错信息并未被标准化,所以,如果你在Visual C++、Borland C++等编译器上看不到这么详细的出错信息,请不必讶异。 <  
1/2 1 2 下一页 尾页 |