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.)
Template Comparison Table
$(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)
)
)
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