Ddoc $(COMMUNITY Template Comparison, $(P 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.) $(TR $(TH Feature) $(TH D) $(TH C++98) $(TH C++0x) ) $(TR $(TD Argument list delineation) $(TD Uses !( ), as in Foo!(int)) $(TD Uses < > as in Foo<int>) $(TD No change) ) $(TR $(TD Class Templates) $(TD Yes: --- class Foo(T) { T x; } --- ) $(TD Yes: $(CPPCODE2 template<class T> class Foo { T x; }; ) ) $(TD No change) ) $(TR $(TD Function Templates) $(TD Yes: --- T foo(T)(T i) { ... } --- ) $(TD Yes: $(CPPCODE2 template<class T> T foo(T i) { ... } ) ) $(TD No change) ) $(TR $(TD Member Templates) $(TD Yes) $(TD Yes) $(TD No change) ) $(TR $(TD Constructor Templates) $(TD No) $(TD Yes) $(TD No change) ) $(TR $(TD Parameterize any Declaration) $(TD Yes, classes, functions, typedefs, variables, enums, etc. can be parameterized, such as this variable: --- template Foo(T) { static T* p; } --- ) $(TD No, only classes and functions) $(TD No change) ) $(TR $(TD Template Typedefs: Create an alias that binds to some but not all of the template parameters) $(TD Yes: --- class Foo(T, U) { } template MyFoo(T) { alias Foo!(T, int) MyFoo; } MyFoo!(uint) f; --- ) $(TD No) $(TD Yes: $(CPPCODE2 template<class T, class U> class Foo { }; template<class T> using MyFoo = Foo<T, int>; MyFoo<unsigned> f; ) ) ) $(TR $(TD Sequence Constructors) $(TD No) $(TD No) $(TD Yes: $(CPPCODE2 Foo<double> f = { 1.2, 3, 6.8 }; ) ) ) $(TR $(TD Concepts) $(V1 $(TD No, but much the same effect can be achieved with $(LINK2 version.html#staticif, static if) and $(LINK2 version.html#StaticAssert, static asserts)) ) $(V2 $(TD Yes: $(LINK2 cpp0x.html#concepts, Constraints)) ) $(TD No) $(TD Yes: $(LINK2 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1849.pdf, Concepts for C++0x N1849)) ) $(TR $(TD Recursive Templates) $(TD Yes: --- template factorial(int n) { const factorial = n * factorial!(n-1); } template factorial(int n : 1) { const factorial = 1; } --- ) $(TD Yes: $(CPPCODE2 template<int n> class factorial { public: enum { result = n * factorial<n-1>::result }; }; template<> class factorial<1> { public: enum { result = 1 }; }; ) ) $(TD No change) ) $(TR $(TD Conditional Compilation based on Template Arguments) $(TD Yes: --- template factorial(int n) { static if (n == 1) const factorial = 1; else const factorial = n * factorial!(n-1); } --- ) $(TD No: $(CPPCODE2 template<int n> class factorial { public: enum { #if (n == 1) // $(ERROR) result = 1; #else result = n * factorial<n-1>::result #endif }; }; ) ) $(TD No change) ) $(TR $(TD Template Declarations (with no definition)) $(TD No) $(TD Yes: $(CPPCODE2 template<class T> class Foo; ) ) $(TD No change) ) $(TR $(TD Grouping templates with the same parameters together) $(TD 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); --- ) $(TD No, each must be separate: $(CPPCODE2 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); ) ) $(TD No change) ) $(TR $(TD Compile time execution of functions) $(TD $(LINK2 function.html#interpretation, Yes): --- int factorial(int i) { if (i == 0) return 1; else return i * factorial(i - 1); } static f = factorial(6); --- ) $(TD No) $(TD Named constant expressions with parameters: $(LINK2 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1972.pdf, Generalized Constant Expressions N1972)) ) $(TR $(TH Parameters) $(TH D) $(TH C++98) $(TH C++0x) ) $(TR $(TD Type Parameters) $(TD Yes: --- class Foo(T) { T x; } Foo!(int) f; --- ) $(TD Yes: $(CPPCODE2 template<class T> class Foo { T x; }; Foo<int> f; ) ) $(TD No change) ) $(TR $(TD Integral Parameters) $(TD Yes: --- void foo(int i)() { int v = i; } --- ) $(TD Yes: $(CPPCODE2 template<int i> void foo() { int v = i; } ) ) $(TD No change) ) $(TR $(TD Pointer Parameters) $(TD Yes, a pointer to object or function) $(TD Yes, a pointer to object or function) $(TD No change) ) $(TR $(TD Reference Parameters) $(TD No, D does not have a general reference type) $(TD Yes: $(CPPCODE2 template<double& D> void foo() { double y = D; } ) ) $(TD No change) ) $(TR $(TD Pointer to Member Parameters) $(TD No, D does not have pointers to members, it has $(LINK2 type.html#delegates, delegates), which can be used as parameters) $(TD Yes) $(TD No change) ) $(TR $(TD Template Template Parameters) $(TD Yes: --- class Foo(T, alias C) { C!(T) x; } --- ) $(TD Yes: $(CPPCODE2 template<class T, template<class U> class C> class Foo { C<T> x; }; ) ) $(TD No change) ) $(TR $(TD Alias Parameters) $(TD 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); --- ) $(TD No) $(TD No change) ) $(TR $(TD Floating Point Parameters) $(TD Yes: --- class Foo(double D) { double x = D; } ... Foo!(1.6) F; --- ) $(TD No) $(TD No change) ) $(TR $(TD String Parameters) $(TD Yes: --- void foo(char[] format)(int i) { writefln(format, i); } ... foo!("i = %s")(3); --- ) $(TD No) $(TD No change) ) $(TR $(TD Local Class Parameters) $(TD Yes) $(TD No) $(TD Issue N1945) ) $(TR $(TD Local Variable Parameters) $(TD Yes) $(TD No) $(TD No change) ) $(TR $(TD Parameter Default Values) $(TD Yes: --- class Foo(T = int) { T x; } --- ) $(TD Yes: $(CPPCODE2 template<class T = int> class Foo { T x; }; ) ) $(TD No change) ) $(TR $(TD Variadic Parameters) $(TD Yes, $(LINK2 variadic-function-templates.html, Variadic Templates): --- void print(A...)(A a) { foreach(t; a) writefln(t); } --- ) $(TD No) $(TD $(LINK2 http://www.osl.iu.edu/~dgregor/cpp/variadic-templates.pdf, Variadic Templates N2080)) ) $(TR $(TH Specializations) $(TH D) $(TH C++98) $(TH C++0x) ) $(TR $(TD Explicit Specialization) $(TD Yes: --- class Foo(T : int) { T x; } --- ) $(TD Yes: $(CPPCODE2 template<> class Foo<int> { int x; }; ) ) $(TD No change) ) $(TR $(TD Partial Specialization) $(TD Yes: --- class Foo(T : T*, U) { T x; } --- ) $(TD Yes: $(CPPCODE2 template<class T, class U> class Foo<T*, U> { T x; }; ) ) $(TD No change) ) $(TR $(TD Partial specialization derived from multiple parameters) $(TD Yes: --- class Foo(T : Bar!(T, U), U) { ... } --- ) $(TD Yes: $(CPPCODE2 template<class T, class U> class Foo< Bar<T,U> > { ... }; ) ) $(TD No change) ) $(TR $(TD Can specializations exist without a primary template?) $(TD Yes) $(TD No) $(TD No change) ) $(TR $(TH Other) $(TH D) $(TH C++98) $(TH C++0x) ) $(TR $(TD Exported Templates) $(TD Yes, it falls out as a natural consequence of modules) $(TD Yes, though only in compilers based on EDG's front end) $(TD No change) ) $(TR $(TD $(SFINAE)) $(TD Yes) $(TD Yes) $(TD No change) ) $(TR $(TD Parse Template Definition Bodies before Instantiation) $(TD Yes) $(TD Not required by Standard, but some implementations do) $(TD No change) ) $(TR $(TD Overloading Function Templates with Functions) $(TD No, but the equivalent can be done with explicitly specialized templates: --- void foo(T)(T t) { } void foo(T:int)(int t) { } --- ) $(TD Yes: $(CPPCODE2 template<class T> void foo(T i) { } void foo(int t) { } ) ) $(TD No change) ) $(TR $(TD Implicit Function Template Instantiation) $(TD Yes) $(TD Yes) $(TD No change) ) $(TR $(TD Templates can be evaluated in scope of instantiation rather than definition) $(TD Yes, $(LINK2 mixin.html, Mixins)) $(TD No, but can be faked using macros) $(TD No change) ) $(TR $(TH Parsing Idiosyncracies) $(TH D) $(TH C++98) $(TH C++0x) ) $(TR $(TD Context-Free Grammar) $(TD Yes: --- class Foo!(int i) { ... } Foo!(3 $(B >) 4) f; --- ) $(TD No: $(CPPCODE2 template<int i> class Foo { ... }; Foo<3 $(B >) 4> f; // $(ERROR) ) ) $(TD No change) ) $(TR $(TD Distinguish template arguments from other operators) $(TD Yes: --- class Foo!(T) { ... } class Bar!(int i) { ... } Foo!(Bar!(1)) x1; --- ) $(TD No: $(CPPCODE2 template<class T> class Foo { ... }; template<int i> class Bar { ... }; Foo<Bar<1>> x1; // $(ERROR) Foo<Bar<1> > x2; ) ) $(TD Partially fixed by $(LINK2 http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1757.html, Right Angle Brackets N1757) ) ) $(TR $(TD Redeclaration of Template Parameter) $(TD Yes: --- class Foo(T) { int T; void foo() { int T; } } --- ) $(TD No: $(CPPCODE2 template<class T> class Foo { int T; // $(ERROR) void foo() { int T; // $(ERROR) } }; ) ) $(TD No change) ) $(TR $(TD Dependent Base Class Lookup) $(TD Yes: --- class Foo(T) { typedef int $(B A); } class Bar(T) : Foo(T) { $(B A) x; } --- ) $(TD No: $(CPPCODE2 template<class T> class Foo { public: typedef int $(B A); }; template<class T> class Bar : Foo<T> { public: $(B A) x; // $(ERROR) }; ) ) $(TD No change) ) $(TR $(TD Forward Referencing) $(TD Yes: --- int $(B g)(void *); class Foo(T) { int foo() { return $(B g)(1); } } int $(B g)(int i); --- ) $(TD No: $(CPPCODE2 int $(B g)(void *); template<class T> class Foo { int foo() { return $(B g)(1); // $(ERROR) } }; int $(B g)(int i); ) ) $(TD No change) ) $(TR $(TD Member templates parseable without hints) $(TD Yes: --- class Foo { Foo bar!(int I)(); } void abd(T)(T f) { T f1 = f.bar!(3)(); } --- ) $(TD No: $(CPPCODE2 class Foo { public: template<int> Foo *bar(); }; template<class T> void abc(T *f) { T *f1 = f->bar<3>(); // $(ERROR) T *f2 = f->$(B template) bar<3>(); } ) ) $(TD No change) ) $(TR $(TD Dependent type members parseable without hints) $(TD Yes: --- class Foo(T) { T.A* a1; } --- ) $(TD No: $(CPPCODE2 template class Foo { public: T::A *a1; // $(ERROR) $(B typename) T::A *a2; }; ) ) $(TD No change) )
Template Comparison Table
) Macros: TITLE=Template Comparison WIKI=TemplateComparison NO=No NO1=No YES=Yes YES1=Yes D_CODE =
$0
CPPCODE2 =
$0
ERROR = $(RED $(B error)) META_KEYWORDS=D Programming Language, template metaprogramming, variadic templates, type deduction, dependent base class META_DESCRIPTION=Comparison of templates between the D programming language, C++, and C++0x