英語版
このページの英語版を見る
テンプレート比較
C++はテンプレートとテンプレートメタプログラミングの先駆けであり、 それを改善し続けてきた。 プログラミング言語Dは、 C++の経験に基づいてテンプレートを総合的に再設計した
| 機能 | D | C++ | 
|---|---|---|
| 引数リストの区切り | Foo!(int) のように、!( ) を使用する。 引数が単一の語彙トークンの場合、括弧は省略できる。Foo!int | < > を使用する。Foo<int> | 
| クラステンプレート | はい: class Foo(T)
{
    T x;
}
 | はい: template<class T>
class Foo
{
    T x;
};
 | 
| 関数テンプレート | はい: T foo(T)(T i)
{
    ...
}
 | はい: template<class T>
T foo(T i)
{
    ...
}
 | 
| メンバーテンプレート | はい | はい | 
| コンストラクタテンプレート | はい | はい | 
| あらゆる宣言のパラメータ化 | はい。クラス、関数、任意のエイリアス、
変数、任意の列挙型などを
パラメータ化できる。
例えば、この変数: template Foo(T) { static T* p; } | いいえ、クラスと関数のみ                C++98 いいえ、クラスと関数のみ C++11 using 型のエイリアスを追加: template<class T> using ptr = T*; ptr<int> p;C++14 constexpr 定数を追加した。 template<class T> constexpr T pi = T(3.1415926535897932385L); | 
| テンプレート型定義:テンプレートパラメータの一部にのみバインドするエイリアスを作成する | はい: class Foo(T, U) { } template MyFoo(T) { alias MyFoo = Foo!(T, int); } MyFoo!(uint) f; | C++98 いいえ C++11 はい: template<class T, class U> class Foo { };
template<class T> using MyFoo = Foo<T, int>;
MyFoo<unsigned> f;
 | 
| シーケンスコンストラクタ | いいえ、代わりに 可変長パラメータを使用する | C++98 いいえ C++11 はい: template <class T>
class Foo {
    Foo(std::initializer_list<T>);
};
Foo<double> f = { 1.2, 3.0, 6.8 };
 | 
| 概念 | はい:制約 | C++98 いいえ C++20 はい:制約と概念 | 
| 再帰的テンプレート | はい: template factorial(int n) { const factorial = n * factorial!(n-1); } template factorial(int n : 1) { const factorial = 1; } | はい: template<int n> class factorial
{
  public:
    enum { result = n * factorial<n-1>::result };
};
template<> class factorial<1>
{
  public:
    enum { result = 1 };
};
 | 
| テンプレート引数に基づく 条件付きコンパイル | はい: void foo(T)(T i) { static if (can_fast_foo!(T)) FastFoo f = fast_foo(i); else SlowFoo f = slow_foo(i); use_foo(f); } class HashTable(T, int maxLength) { static if (maxLength < 0xFFFE) alias CellIdx = ushort; else alias CellIdx = uint; CellIdx index; } | C++98 いいえ、ただし回避策あり: template<class T> void foo(T i)
{
  // Helper<bool>の特殊化を
  // 使用して区別する
  Helper<can_fast_foo<T>>::use_foo(i);
};
template<class T, int maxLength> class HashTable {
    typedef typename std::conditional<
            maxLength < 0xFFFE, uint16_t, uint32_t>
        ::type CellIdx;
    CellIdx index;
};
C++17 はい、ただしブロックスコープに限定されます。 template<class T> void foo(T i)
{
  if constexpr (can_fast_foo<T>)
    FastFoo foo = fast_foo(i);
  else
    SlowFoo foo = slow_foo(i);
  use_foo(foo); // エラー fooは宣言されていない
}
template<class T, int maxLength> class HashTable {
    // エラー 関数外では'if'が使えない
    if constexpr (maxLength < 0xFFFE)
        using CellIdx = ushort;
    else
        using CellIdx = uint;
    CellIdx index;
};
 | 
| テンプレートフォワード宣言 | 必要ない | はい: template<class T> class Foo; | 
| 同じパラメータを持つテンプレートをグループ化する | はい: template Foo(T, U) { class Bar { ... } T foo(T t, U u) { ... } } Foo!(int,long).Bar b; return Foo!(char,int).foo('c',3); | ある程度可能。クラスのメンバーを使用して: template<class T, class U>
class Foo {
    class Bar { ... };
    static T foo(T t, U u) { ... }
};
Foo<int, long>::bar b;
return Foo<char, int>::foo('c', 3);
 | 
| this パラメータの型を推測する | はい | C++23 はい | 
| 関数のコンパイル時実行 | はい: int factorial(int i) { if (i == 0) return 1; else return i * factorial(i - 1); } pragma(msg, factorial(6)); | C++98 いいえ C++11 はい、ただしconstexpr関数のみ。 C++11ではconstexprは厳しく制限されていたが、その後の各標準ではこれらの制限が緩和されている。 | 
| パラメータ | D | C++ | 
| 型パラメータ | はい: class Foo(T) { T x; } Foo!(int) f; | はい: template<class T>
class Foo
{
    T x;
};
Foo<int> f;
 | 
| 整数パラメータ | はい: void foo(int i)() { int v = i; } | はい: template<int i>
void foo()
{
    int v = i;
}
 | 
| ポインタパラメータ | はい、オブジェクトまたは関数へのポインタ | はい、オブジェクトまたは関数へのポインタ | 
| 参照パラメータ | いいえ。ただし、エイリアス・パラメータを代わりに使用できる(下記参照)。 | はい: template<double& D>
void foo()
{
    double y = D;
}
 | 
| メンバパラメータへのポインタ | いいえ、Dにはメンバーへのポインタはない。 しかし、 デリゲートはあり、これはパラメータとして使用できる | はい | 
| テンプレート テンプレート パラメータ | はい: class Foo(T, alias C) { C!(T) x; } | はい: template<class T,
         template<class U> class C>
class Foo
{
    C<T> x;
};
 | 
| エイリアスパラメータ | はい、任意のシンボルをエイリアスとしてテンプレートに渡すことができる。 void bar(int); void bar(double); void foo(T, alias S)(T t) { S(t); } // bar(double)を呼び出す foo!(double, bar)(1); | いいえ | 
| 浮動小数点パラメータ | はい: class Foo(double D) { double x = D; } ... Foo!(1.6) F; | C++98 いいえ C++11 はい: template<float f>
void foo()
{
    int v = f;
}
 | 
| 文字列パラメータ | はい: void foo(string format)(int i) { writefln(format, i); } ... foo!("i = %s")(3); | C++98 いいえ C++17 間接的にのみ: template <const char *str>
struct S {};
S<"Foo"> foo1; // エラー 文字列リテラル引数は依然として不正である
const char foo_str[] = "foo";
S<foo_str> foo2; // リテラル型は許可されており、配列も含まれる。
 | 
| ローカルクラスパラメータ | はい | C++98 いいえ C++17 はい | 
| ローカル変数パラメータ | はい | いいえ | 
| パラメータのデフォルト値 | はい: class Foo(T = int) { T x; } | はい: template<class T = int>
class Foo
{
    T x;
};
 | 
| 可変長パラメータ | 可変長テンプレート: void print(A...)(A a) { foreach(t; a) writeln(t); } | C++98 いいえ C++11 はい: // 最後の引数を処理するには、
// 引数ゼロまたは引数1のバージョンが必要だ。
void print() {};
template <class Arg, class... Args>
void print(const Arg& arg, Args&&... args)
{
    writeln(arg);
    print(std::forward<Args>(args)...);
}
上記の例は、
                C++17でFold式を使用して多少改善されている
                ことに注意。template <class Args...>
void print(Args...&& args)
{
    (writeln(std::forward<Args.>(args)), ...);
}
 | 
| 特殊化 | D | C++ | 
| 明示的特化 | はい: class Foo(T : int) { T x; } | はい: template<>
class Foo<int>
{
    int x;
};
 | 
| 部分特殊化 | はい: class Foo(T : T*, U)
{
    T x;
}
 | はい: template<class T, class U>
class Foo<T*, U>
{
    T x;
};
 | 
| 複数のパラメータから派生する部分的な専門性 | はい: class Foo(T : Bar!(T, U), U)
{
    ...
}
 | はい: template<class T, class U>
class Foo< Bar<T,U> >
{
    ...
};
 | 
| 主要テンプレートなしで専門分野は存在し得るか? | はい | いいえ | 
| その他 | D | C++ | 
| エクスポートされたテンプレート | はい、モジュールの自然な結果として除外される | C++98 はい、ただしEDGのフロントエンドに基づくコンパイラでのみサポートされていた。 C++11 サポート不足により言語から削除された。 | 
| SFINAE(Substitution Failure Is Not An Error) | いいえ | はい | 
| インスタンス化の前にテンプレート定義本体を解析する | はい | 標準では必須ではないが、実装によっては必要となる | 
| 関数テンプレートのオーバーロード | はい: void foo(T)(T t) { } void foo(int i) { } | はい: template<class T>
void foo(T t) { }
void foo(int i) { }
 | 
| 暗黙的な関数テンプレートのインスタンス化 | はい | はい | 
| テンプレートは定義ではなくインスタンス化のスコープで評価できる | はい、テンプレートミックスイン | いいえ。ただし、マクロを使用して擬似的に実現可能 | 
| テンプレートインスタンスの引数を抽出できる | はい: struct Bar(T1, T2) { } alias BarInst = Bar!(int, float); static if (is(BarInst : Template!Args, alias Template, Args...)) { pragma(msg, Args); // (int, float) } | いいえ | 
| パーシングの特殊性 | D | C++ | 
| 文脈自由文法 | はい: class Foo(int i) { ... } Foo!(3 > 4) f; | いいえ: template<int i> class Foo
{
    ...
};
Foo<3 > 4> f; // エラー 
 | 
| テンプレート引数と他の演算子を区別する | はい: class Foo(T) { ... } class Bar(int i) { ... } Foo!(Bar!(1)) x1; | C++98 いいえ: template<class T> class Foo
{
    ...
};
template<int i> class Bar
{
    ...
};
Foo<Bar<1>> x1; // エラー 
Foo<Bar<1> > x2;
C++11 右大括弧で部分的に修正済みN1757 | 
| テンプレートパラメータの再宣言 | はい: class Foo(T) { int T; void foo() { int T; } } | いいえ: template<class T>
class Foo
{
    int T; // エラー 
    void foo()
    {
        int T; // エラー 
    }
};
 | 
| 依存するベースクラスの検索 | はい: class Foo(T) { alias A = int; } class Bar(T) : Foo(T) { A x; } | いいえ: template<class T>
class Foo
{
  public:
    typedef int A;
};
template<class T>
class Bar : Foo<T>
{
  public:
    A x; // エラー 
};
 | 
| 前方参照 | はい: int g(void *); class Foo(T) { int foo() { return g(1); } } int g(int i); | いいえ: int g(void *);
template<class T>
class Foo
{
    int foo()
    {
        return g(1); // エラー 
    }
};
int g(int i);
 | 
| ヒントなしで解析可能なメンバーテンプレート | はい: class Foo { Foo bar!(int I)(); } void abd(T)(T f) { T f1 = f.bar!(3)(); } | いいえ: class Foo
{
  public:
    template<int> Foo *bar();
};
template<class T> void abc(T *f)
{
    T *f1 = f->bar<3>(); // エラー 
    T *f2 = f->template bar<3>();
}
 | 
| ヒントなしで解析可能な依存型メンバ | はい: class Foo(T)
{
    T.A* a1;
}
 | いいえ: template<class T> class Foo
{
  public:
    T::A *a1; // エラー 
    typename T::A *a2;
};
 | 
Copyright © 1999-2025 by the D Language Foundation
DEEPL APIにより翻訳、ところどころ修正。
このページの最新版(英語)
このページの原文(英語)
翻訳時のdmdのバージョン: 2.109.1
サイト全体のドキュメントのdmdのバージョン: 2.109.1
最新のdmdのバージョン: 2.111.0 ダウンロード
翻訳日付:
HTML生成日時:
編集者: dokutoku