C++ pioneered templates and template metaprogramming, and continuesto improve on it with C++0x.The D programming language is the first to comprehensively reengineertemplates based on the C++ experience.Since C++0x is not a ratified standard yet, proposed changes to C++are subject to change.
| Feature | D | C++98 | C++0x |
|---|---|---|---|
| Argument list delineation | Uses !( ), as in Foo!(int) | Uses < > as in Foo<int> | No change |
| Class Templates | Yes:class Foo(T){ T x;} | Yes:template<class T> class Foo{ T x;}; | No change |
| Function Templates | Yes:T foo(T)(T i){ ...} | Yes:template<class T> T foo(T i){ ...} | No change |
| Member Templates | Yes | Yes | No change |
| Constructor Templates | No | Yes | No change |
| Parameterize any Declaration | Yes, classes, functions, typedefs,variables, enums, etc. can be parameterized,such as this variable:template Foo(T){static T* p;} | No, only classes and functions | No change |
| Template Typedefs: Create an alias that binds to some but not allof the templateparameters | Yes:class Foo(T, U) { }template MyFoo(T){alias Foo!(T,int) MyFoo;}MyFoo!(uint) f; | No | Yes:template<class T, class U> class Foo { };template<class T> using MyFoo = Foo<T, int>;MyFoo<unsigned> f; |
| Sequence Constructors | No | No | Yes:Foo<double> f = { 1.2, 3, 6.8 }; |
| Concepts | No, but much the same effect can be achieved withStaticIfCondition andstatic asserts | No | Yes:Concepts for C++0x N1849 |
| Recursive Templates | Yes:template factorial(int n){const factorial = n * factorial!(n-1);}template factorial(int n : 1){const factorial = 1;} | Yes:template<int n> class factorial{ public: enum { result = n * factorial<n-1>::result }; };template<> class factorial<1>{ public: enum { result = 1 };}; | No change |
| Conditional Compilation based onTemplate Arguments | Yes:template factorial(int n){staticif (n == 1)const factorial = 1;elseconst factorial = n * factorial!(n-1);} | No:template<int n> class factorial{ public: enum {#if (n == 1) //error result = 1;#else result = n * factorial<n-1>::result#endif }; }; | No change |
| Template Declarations (with no definition) | No | Yes:template<class T> class Foo; | No change |
| Grouping templates with the same parameters together | Yes:template Foo(T, U){class Bar { ... } T foo(T t, U u) { ... }}Foo!(int,long).Bar b;return Foo!(char,int).foo('c',3); | No, each must be separate:template<class T, class U> class Foo_Bar { ... };template<class T, class U> T Foo_foo(T t, U u) { ... };Foo_Bar<int,long> b;return Foo_foo<char,int>('c',3); | No change |
| Compile time execution of functions | Yes:int factorial(int i){if (i == 0)return 1;elsereturn i * factorial(i - 1);}static f = factorial(6); | No | Named constant expressions with parameters:Generalized Constant Expressions N1972 |
| Parameters | D | C++98 | C++0x |
| Type Parameters | Yes:class Foo(T){ T x;}Foo!(int) f; | Yes:template<class T> class Foo{ T x;};Foo<int> f; | No change |
| Integral Parameters | Yes:void foo(int i)(){int v = i;} | Yes:template<int i> void foo(){ int v = i;} | No change |
| Pointer Parameters | Yes, a pointer to object or function | Yes, a pointer to object or function | No change |
| Reference Parameters | No, D does not have a general reference type | Yes:template<double& D> void foo(){ double y = D;} | No change |
| Pointer to Member Parameters | No, D does not have pointers to members, it hasdelegates, which can be used as parameters | Yes | No change |
| Template Template Parameters | Yes:class Foo(T,alias C){ C!(T) x;} | Yes:template<class T, template<class U> class C> class Foo{ C<T> x;}; | No change |
| Alias Parameters | Yes, any symbol can be passed to a template as an alias:void bar(int);void bar(double);void foo(T,alias S)(T t){ S(t);}// calls bar(double)foo!(double, bar)(1); | No | No change |
| Floating Point Parameters | Yes:class Foo(double D){double x = D;}...Foo!(1.6) F; | No | No change |
| String Parameters | Yes:void foo(char[] format)(int i){ writefln(format, i);}...foo!("i = %s")(3); | No | No change |
| Local Class Parameters | Yes | No | Issue N1945 |
| Local Variable Parameters | Yes | No | No change |
| Parameter Default Values | Yes:class Foo(T =int){ T x;} | Yes:template<class T = int> class Foo{ T x;}; | No change |
| Variadic Parameters | Yes,Variadic Templates:void print(A...)(A a){foreach(t; a)writefln(t);} | No | Variadic Templates N2080 |
| Specializations | D | C++98 | C++0x |
| Explicit Specialization | Yes:class Foo(T :int){ T x;} | Yes:template<> class Foo<int>{ int x;}; | No change |
| Partial Specialization | Yes:class Foo(T : T*, U){ T x;} | Yes:template<class T, class U> class Foo<T*, U>{ T x;}; | No change |
| Partial specialization derived from multiple parameters | Yes:class Foo(T : Bar!(T, U), U){ ...} | Yes:template<class T, class U> class Foo< Bar<T,U> >{ ...}; | No change |
| Can specializations exist without a primary template? | Yes | No | No change |
| Other | D | C++98 | C++0x |
| Exported Templates | Yes, it falls out as a natural consequence of modules | Yes, though only in compilers based on EDG's front end | No change |
| SFINAE (Substitution Failure Is Not An Error) | Yes | Yes | No change |
| Parse Template Definition Bodies before Instantiation | Yes | Not required by Standard, but some implementations do | No change |
| Overloading Function Templates with Functions | No, but the equivalent can be done with explicitly specializedtemplates:void foo(T)(T t) { }void foo(T:int)(int t) { } | Yes:template<class T> void foo(T i) { }void foo(int t) { } | No change |
| Implicit Function Template Instantiation | Yes | Yes | No change |
| Templates can be evaluated in scope of instantiation rather than definition | Yes,Mixins | No, but can be faked using macros | No change |
| Parsing Idiosyncracies | D | C++98 | C++0x |
| Context-Free Grammar | Yes:class Foo!(int i){ ...}Foo!(3> 4) f; | No:template<int i> class Foo{ ...};Foo<3> 4> f; //error | No change |
| Distinguish template arguments from other operators | Yes:class Foo!(T){ ...}class Bar!(int i){ ...}Foo!(Bar!(1)) x1; | No:template<class T> class Foo{ ...};template<int i> class Bar{ ...};Foo<Bar<1>> x1; //errorFoo<Bar<1> > x2; | Partially fixed byRight Angle Brackets N1757 |
| Redeclaration of Template Parameter | Yes:class Foo(T){int T;void foo() {int T; }} | No:template<class T> class Foo{ int T; //error void foo() { int T; //error }}; | No change |
| Dependent Base Class Lookup | Yes:class Foo(T){typedefintA;}class Bar(T) : Foo(T){A x;} | No:template<class T> class Foo{ public: typedef intA;};template<class T> class Bar : Foo<T>{ public:A x; //error}; | No change |
| Forward Referencing | Yes:intg(void *);class Foo(T){int foo() {returng(1); }}intg(int i); | No:intg(void *);template<class T> class Foo{ int foo() { returng(1); //error }};intg(int i); | No change |
| Member templates parseable without hints | Yes:class Foo{ Foo bar!(int I)();}void abd(T)(T f){ T f1 = f.bar!(3)();} | No:class Foo{ public: template<int> Foo *bar();};template<class T> void abc(T *f){ T *f1 = f->bar<3>(); //error T *f2 = f->template bar<3>();} | No change |
| Dependent type members parseable without hints | Yes:class Foo(T){ T.A* a1;} | No:template | No change |