Template Comparison – D vs. C++


Report a bug If you spot a problem with this page, click here to create a Bugzilla issue. Improve this page Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using local clone.

Template Comparison

C++ pioneered templates and template metaprogramming, and continues to improve on it with C++0x. The D programming language is the first to comprehensively reengineer templates based on the C++ experience. Since C++0x is not a ratified standard yet, proposed changes to C++ are subject to change.

Template Comparison Table Feature D C++98 C++0x Argument list delineation Uses !( ), as in Foo!(int).Can omit parens when the argument is a single lexical token: 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 all of the template parameters Yes: class Foo(T, U) { }template MyFoo(T){ alias MyFoo = Foo!(T, int);}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 Yes:Constraints 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 on Template Arguments Yes: template factorial(int n){ static if (n == 1) const factorial = 1; else const 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; else return 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) writeln(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)">sfinae, 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 specialized templates: 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 Can extract arguments of template instance Yes: class Foo(T){static if (is(T x : T!A, A...)){pragma(msg, A); // (int, float)}}struct Bar(T1, T2) { }alias BarInst = Bar!(int, float);Foo!(BarInst) f;Seeis expressions. No 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 by Right 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){ alias A = int;}class Bar(T) : Foo(T){ A x;} No: template<class T>class Foo{ public: typedef int A;};template<class T>class Bar : Foo<T>{ public: A x; // error}; No change Forward Referencing Yes: int g(void *);class Foo(T){int foo(){return g(1);}}int g(int i); No: int g(void *);template<class T>class Foo{int foo(){return g(1); // error}};int g(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 class Foo{ public: T::A *a1; // error typename T::A *a2;}; No change