D Programming Language
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.

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 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 | 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)
    	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 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 Bar!(int, float) BarInst;
    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)
    {
      typedef int A;
    }
    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

Forums | Comments | Search | Downloads | Home
Copyright © 1999-2013 by Digital Mars ®, All Rights Reserved | Page generated by Ddoc on Tue May 28 10:49:29 2013