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.
Page wiki
View or edit the community-maintained wiki page associated with this page.
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.
| 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 has delegates, 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;See is 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; // error
Foo<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 |
No change |