D 1.0   D 2.0
About Japanese Translation

Last update Sun Dec 13 17:45:47 2009

テンプレートの比較

C++ がテンプレートとテンプレートメタプログラミングの先駆けとなり、 C++0x へと改善が進んでいます。 プログラミング言語 D は、 C++ での経験に基づいて、 テンプレートを完全に設計し直した最初の言語です。

テンプレート比較表
機能 D C++98 C++0x
引数の渡し方 !( ) を使う: Foo!(int) < > を使う: Foo<int> 変更なし
クラステンプレート Yes:
class Foo(T)
{
  T x;
}
Yes:
template<class T>
  class Foo
{
  T x;
};
変更なし
関数テンプレート Yes:
T foo(T)(T i)
{
  ...
}
Yes:
template<class T>
  T foo(T i)
{
  ...
}
変更なし
メンバテンプレート Yes Yes 変更なし
コンストラクタテンプレート No Yes 変更なし
任意の宣言のパラメタ化 Yes。クラス、関数、typedef、 変数、enum などがパラメタ化できます。 以下の例のように:
template Foo(T)
{
  static T* p;
}
No。クラスと関数のみ 変更なし
typedefテンプレート: テンプレート引数を使った宣言への alias を作る 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;
シーケンス・コンストラクタ No No Yes:
Foo<double> f = { 1.2, 3, 6.8 };
Concept No。しかし、同じ効果を static ifstatic asserts で実現できます。 No Yes: Concepts for C++0x N1849
再帰テンプレート 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 };
};
変更なし
テンプレート引数に基づく 条件コンパイル 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 Yes:
template<class T>
  class Foo;
変更なし
同じ引数のテンプレートのグループ化 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。それぞれ分離して書きます:
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);
変更なし
関数のコンパイル時実行 Yes:
int factorial(int i)
{ if (i == 0)
    return 1;
  else
    return i * factorial(i - 1);
}
static f = factorial(6);
No パラメタでの名前付き定数式: Generalized Constant Expressions N1972
引数 D C++98 C++0x
型引数 Yes:
class Foo(T)
{
  T x;
}
Foo!(int) f;
Yes:
template<class T>
  class Foo
{
  T x;
};
Foo<int> f;
変更なし
整数引数 Yes:
void foo(int i)()
{
  int v = i;
}
Yes:
template<int i>
    void foo()
{
  int v = i;
}
変更なし
ポインタ引数 Yes。オブジェクトか関数へのポインタ Yes。オブジェクトか関数へのポインタ 変更なし
参照引数 No, D には参照型がありません Yes:
template<double& D>
    void foo()
{
  double y = D;
}
変更なし
メンバポインタ引数 No, D にはメンバへのポインタがありません。代わりに delegates があって、これは引数として使えます Yes 変更なし
テンプレートテンプレート引数 Yes:
class Foo(T, alias C)
{
  C!(T) x;
}
Yes:
template<class T,
         template<class U> class C>
    class Foo
{
  C<T> x;
};
変更なし
alias 引数 Yes, 任意のシンボルをテンプレート引数にaliasとして渡すことが可能:
void bar(int);
void bar(double);
void foo(T, alias S)(T t)
{
  S(t);
}
// bar(double) を呼ぶ
foo!(double, bar)(1);
No 変更なし
浮動小数点数引数 Yes:
class Foo(double D)
{
  double x = D;
}
...
Foo!(1.6) F;
No 変更なし
文字列引数 Yes:
void foo(char[] format)(int i)
{
  writefln(format, i);
}
...
foo!("i = %s")(3);
No 変更なし
ローカルクラス引数 Yes No Issue N1945
ローカル変数引数 Yes No 変更なし
引数のデフォルト値 Yes:
class Foo(T = int)
{
  T x;
}
Yes:
template<class T = int>
  class Foo
{
  T x;
};
変更なし
可変個引数 Yes, Variadic Templates:
void print(A...)(A a)
{
    foreach(t; a)
	writefln(t);
}
No Variadic Templates N2080
特殊化 D C++98 C++0x
明示的特殊化 Yes:
class Foo(T : int)
{
  T x;
}
Yes:
template<>
  class Foo<int>
{
  int x;
};
変更なし
部分特殊化 Yes:
class Foo(T : T*, U)
{
  T x;
}
Yes:
template<class T, class U>
  class Foo<T*, U>
{
  T x;
};
変更なし
複数パラメタによる部分特殊化 Yes:
class Foo(T : Bar!(T, U), U)
{
  ...
}
Yes:
template<class T, class U>
    class Foo< Bar<T,U> >
{
  ...
};
変更なし
プライマリテンプレートなしの特殊化 Yes No 変更なし
その他 D C++98 C++0x
テンプレートのexport Yes, モジュールを導入した自然な帰結です Yes, ただしEDGのフロントエンドを使ったコンパイラのみ 変更なし
SFINAE (Substitution Failure Is Not An Error) Yes Yes 変更なし
インスタンス化の前のテンプレート定義本体の構文解析 Yes 標準では要求されていないが、いくつかの実装はそうなっている 変更なし
関数テンプレートと関数のオーバーロード No, しかし、同等の効果が 明示的に特殊化したテンプレートで実現できます:
void foo(T)(T t) { }
void foo(T:int)(int t) { }
Yes:
template<class T>
  void foo(T i) { }
void foo(int t) { }
変更なし
関数テンプレートの暗黙のインスタンス化 Yes Yes 変更なし
定義ではなくインスタンス化のスコープでの テンプレートの評価 Yes, Mixins No, マクロで真似をすることは可能 変更なし
構文的な特徴 D C++98 C++0x
文脈自由文法 Yes:
class Foo!(int i)
{
   ...
}
Foo!(3 > 4) f;
No:
template<int i> class Foo
{
   ...
};
Foo<3 > 4> f; // error
変更なし
テンプレート引数と他の演算子の区別 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;
Right Angle Brackets N1757 で部分的に改善
テンプレート引数の再宣言 Yes:
class Foo(T)
{
  int T;
  void foo()
  {
    int T;
  }
}
No:
template<class T>
  class Foo
{
  int T; // error
  void foo()
  {
    int T; // error
  }
};
変更なし
基底クラスの依存型の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
};
変更なし
前方参照 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);
変更なし
ヒントなしでメンバテンプレートの構文解析可能 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>();
}
変更なし
ヒントなしで依存メンバ型が構文解析可能 Yes:
class Foo(T)
{
  T.A* a1;
}
No:
template class Foo
{
  public:
    T::A *a1; // error
    typename T::A *a2;
};
変更なし