Namespaces
Variants

Template parameters

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

すべての template は、1つ以上のテンプレートパラメータによってパラメータ化されます。

template-parameter-list 内のパラメータ( template declaration syntax を参照)は以下のカテゴリのいずれかに属します:

  • 定数テンプレートパラメータ
  • 型テンプレートパラメータ
  • テンプレートテンプレートパラメータ

目次

翻訳の説明: - 「Contents」→「目次」に翻訳 - 「Notes」→「注記」に翻訳 - 「Examples」→「例」に翻訳 - 「Defect reports」→「欠陥報告」に翻訳 - C++専門用語(Constant template parameter、Type template parameter、Template template parameter、Name resolution for template parameters、Default template arguments)は原文のまま保持 - HTMLタグ、属性、クラス名、IDは一切変更せず保持 - 番号やリンク構造は完全に維持

定数テンプレートパラメータ

別名 non-type template parameter 下記 を参照)。

type name  (オプション) (1)
type name  (オプション) = default (2)
type ... name  (オプション) (3) (C++11以降)
type - 以下の型のいずれか:
  • 構造化型 (下記参照)
(C++17以降)
(C++20以降)
name - 定数テンプレートパラメータの名前
default - デフォルトテンプレート引数 default template argument
1) 定数テンプレートパラメータ。
2) デフォルトテンプレート引数を持つ定数テンプレートパラメータ。
3) 定数テンプレート parameter pack


構造体型 は以下のいずれかの型です(任意でcv修飾可能、修飾子は無視されます):

(C++11以降)
  • すべての基底クラスと非静的データメンバーがpublicかつ非mutableであり、
  • すべての基底クラスと非静的データメンバーの型が構造的型または(多次元可能性のある)その配列である。
(C++20以降)

配列型と関数型はテンプレート宣言で記述できますが、適切なオブジェクトへのポインタと関数へのポインタに自動的に置き換えられます。

定数テンプレートパラメータの名前がクラステンプレート本体の式内で使用される場合、その型が左辺値参照型でない限り、変更不可能な prvalue となります 。またはその型がクラス型でない限り (C++20以降)

class Foo という形式のテンプレートパラメータは、 Foo 型の無名定数テンプレートパラメータではありません。 たとえ通常の文脈では class Foo elaborated type specifier であり、 class Foo x; x Foo 型として宣言する場合でも同様です。

クラス型 T の定数テンプレートパラメータを名前とする 識別子 は、 const T 型の静的記憶域期間を持つオブジェクトを表し、 テンプレートパラメータオブジェクト と呼ばれる。これは、対応するテンプレート引数がテンプレートパラメータの型に変換された後に テンプレート引数等価 となる。2つのテンプレートパラメータオブジェクトがテンプレート引数等価になることはない。

struct A
{
    friend bool operator==(const A&, const A&) = default;
};
template<A a>
void f()
{
    &a;                       // OK
    const A& ra = a, &rb = a; // Both bound to the same template parameter object
    assert(&ra == &rb);       // passes
}
(C++20以降)

型テンプレートパラメータ

type-parameter-key name  (オプション) (1)
type-parameter-key name  (オプション) = default (2)
type-parameter-key ... name  (オプション) (3) (C++11以降)
type-constraint name  (オプション) (4) (C++20以降)
type-constraint name  (オプション) = default (5) (C++20以降)
type-constraint ... name  (オプション) (6) (C++20以降)
type-parameter-key - typename または class のいずれか。型テンプレートパラメータ宣言において、これらのキーワード間に違いはない
type-constraint - concept の名前、またはconceptの名前とそれに続くテンプレート引数のリスト(角括弧内)のいずれか。いずれの場合も、concept名は任意で修飾可能
name - 型テンプレートパラメータの名前
default - デフォルトテンプレート引数
1) デフォルト値を持たない型テンプレートパラメータ。
template<class T>
class My_vector { /* ... */ };
2) デフォルト値を持つ型テンプレートパラメータ
template<class T = void>
struct My_op_functor { /* ... */ };
3) 型テンプレート parameter pack .
template<typename... Ts>
class My_tuple { /* ... */ };
4) デフォルト値を持たない制約付き型テンプレートパラメータ。
template<My_concept T>
class My_constrained_vector { /* ... */ };
5) デフォルト値を持つ制約付き型テンプレートパラメータ。
template<My_concept T = void>
class My_constrained_op_functor { /* ... */ };
6) 制約付き型テンプレート parameter pack .
template<My_concept... Ts>
class My_constrained_tuple { /* ... */ };


パラメータ名はオプションです:

// 上記で示したテンプレートの宣言:
template<class>
class My_vector;
template<class = void>
struct My_op_functor;
template<typename...>
class My_tuple;

テンプレート宣言の本体では、型パラメータの名前はtypedef名であり、テンプレートがインスタンス化されたときに提供される型のエイリアスとなります。

制約付きテンプレートパラメータ P 型制約 が概念 C を指定する Q である場合、以下の規則に従って 制約式 E が導入されます:

  • Q C (引数リストなし)の場合、
  • P がパラメータパックでない場合、 E は単に C<P> となります
  • それ以外の場合( P がパラメータパックである場合)、 E は畳み込み式 (C<P> && ...) となります
  • Q C<A1,A2...,AN> の場合、 E はそれぞれ C<P,A1,A2,...AN> または (C<P,A1,A2,...AN> && ...) となります
template<typename T>
concept C1 = true;
template<typename... Ts> // variadic concept
concept C2 = true;
template<typename T, typename U>
concept C3 = true;
template<C1 T>         struct s1; // constraint-expression is C1<T>
template<C1... T>      struct s2; // constraint-expression is (C1<T> && ...)
template<C2... T>      struct s3; // constraint-expression is (C2<T> && ...)
template<C3<int> T>    struct s4; // constraint-expression is C3<T, int>
template<C3<int>... T> struct s5; // constraint-expression is (C3<T, int> && ...)
(C++20以降)

テンプレートテンプレートパラメータ

template < parameter-list > type-parameter-key name  (オプション) (1)
template < parameter-list > type-parameter-key name  (オプション) = default (2)
template < parameter-list > type-parameter-key ... name  (オプション) (3) (C++11以降)
type-parameter-key - class または typename (C++17以降)
1) オプションの名前を持つテンプレートテンプレートパラメータ。
2) オプションの名前とデフォルト値を持つテンプレートテンプレートパラメータ。
3) テンプレートテンプレート parameter pack とオプションの名前。


テンプレート宣言の本体では、このパラメータの名前はテンプレート名です(インスタンス化するには引数が必要です)。

template<typename T>
class my_array {};
// 2つの型テンプレートパラメータと1つのテンプレートテンプレートパラメータ:
template<typename K, typename V, template<typename> typename C = my_array>
class Map
{
    C<K> key;
    C<V> value;
};

テンプレートパラメータの名前解決

テンプレートパラメータの名前は、そのスコープ内(ネストされたスコープを含む)で再宣言することはできません。テンプレートパラメータはテンプレート名と同じ名前を持つことは許可されていません。

template<class T, int N>
class Y
{
    int T;      // エラー: テンプレートパラメータの再宣言
    void f()
    {
        char T; // エラー: テンプレートパラメータの再宣言
    }
};
template<class X>
class X; // エラー: テンプレートパラメータの再宣言

クラステンプレートの定義外で現れるクラステンプレートのメンバーの定義において、クラステンプレートのメンバーの名前は、任意の外側のクラステンプレートのテンプレートパラメータの名前を隠しますが、そのメンバーがクラスまたは関数テンプレートである場合、そのメンバーのテンプレートパラメータは隠しません。

template<class T>
struct A
{
    struct B {};
    typedef void C;
    void f();
    template<class U>
    void g(U);
};
template<class B>
void A<B>::f()
{
    B b; // AのB、テンプレートパラメータではない
}
template<class B>
template<class C>
void A<B>::g(C)
{
    B b; // AのB、テンプレートパラメータではない
    C c; // テンプレートパラメータC、AのCではない
}

クラステンプレートの定義を含む名前空間の外部に現れるクラステンプレートのメンバーの定義において、テンプレートパラメータの名前はこの名前空間のメンバーの名前を隠蔽します。

namespace N
{
    class C {};
    template<class T>
    class B
    {
        void f(T);
    };
}
template<class C>
void N::B<C>::f(C)
{
    C b; // C はテンプレートパラメータであり、N::C ではない
}

クラステンプレートの定義内、またはそのテンプレート定義外で現れるそのようなテンプレートのメンバーの定義において、非 dependent 基底クラスごとに、基底クラスの名前または基底クラスのメンバーの名前がテンプレートパラメータの名前と同じである場合、基底クラス名またはメンバー名はテンプレートパラメータ名を隠蔽します。

struct A
{
    struct B {};
    int C;
    int Y;
};
template<class B, class C>
struct X : A
{
    B b; // AのB
    C b; // エラー: AのCは型名ではない
};

デフォルトテンプレート引数

デフォルトテンプレート引数は、パラメータリスト内で = 記号の後に指定されます。デフォルト値はあらゆる種類のテンプレートパラメータ(型、定数、またはテンプレート)に対して指定できます 、ただしパラメータパックには指定できません (C++11以降)

プライマリクラステンプレートのテンプレートパラメータに対してデフォルトが指定された場合 、プライマリ変数テンプレート、 (C++14以降) またはエイリアステンプレートでは、後続の各テンプレートパラメータはデフォルト引数を持たなければならない 。ただし、最後のパラメータのみがテンプレートパラメータパックであってもよい (C++11以降) 。関数テンプレートでは、デフォルト値を持つパラメータに続くパラメータに制限はない 。また、パラメータパックの後にさらに型パラメータが続く場合、それらはデフォルト値を持つか、関数引数から推論可能でなければならない (C++11以降)

デフォルトパラメータは許可されていません

(C++11以前)

フレンド関数テンプレートの宣言において、デフォルトテンプレート引数は、その宣言が定義であり、かつこの翻訳単位にこの関数の他の宣言が存在しない場合にのみ許可されます。

(since C++11)

宣言内に現れるデフォルトテンプレート引数は、デフォルト関数引数と同様にマージされます:

template<typename T1, typename T2 = int> class A;
template<typename T1 = int, typename T2> class A;
// 上記は以下と同じ:
template<typename T1 = int, typename T2 = int> class A;

しかし、同じパラメータに対して同じスコープ内でデフォルト引数を2回指定することはできません:

template<typename T = int> class X;
template<typename T = int> class X {}; // エラー

定数テンプレートパラメータのデフォルトテンプレート引数を解析する際、最初のネストされていない > は、大なり演算子ではなくテンプレートパラメータリストの終了として扱われます:

template<int i = 3 > 4>   // 構文エラー
class X { /* ... */ };
template<int i = (3 > 4)> // OK
class Y { /* ... */ };

テンプレートテンプレートパラメータのテンプレートパラメータリストは、独自のデフォルト引数を持つことができます。これらのデフォルト引数は、テンプレートテンプレートパラメータ自体がスコープ内にある場合にのみ有効です:

// クラステンプレート、デフォルト値を持つ型テンプレートパラメータ付き
template<typename T = float>
struct B {};
// テンプレートテンプレートパラメータTはパラメータリストを持ち、
// それはデフォルト値を持つ1つの型テンプレートパラメータで構成される
template<template<typename = float> typename T>
struct A
{
    void f();
    void g();
};
// 外部定義のメンバ関数テンプレート
template<template<typename TT> class T>
void A<T>::f()
{
    T<> t; // エラー: スコープ内でTTにデフォルト値がありません
}
template<template<typename TT = char> class T>
void A<T>::g()
{
    T<> t; // OK: tはT<char>です
}

Member access デフォルトテンプレートパラメータで使用される名前のメンバーアクセスは、使用時点ではなく宣言時点でチェックされます:

class B {};
template<typename T>
class C
{
protected:
    typedef T TT;
};
template<typename U, typename V = typename U::TT>
class D: public U {};
D<C<B>>* d; // エラー: C::TT は protected です

デフォルトテンプレート引数は、そのデフォルト引数の値が必要とされるときに暗黙的にインスタンス化されます。ただし、テンプレートが関数の名前を指定するために使用される場合は除きます:

template<typename T, typename U = int>
struct S {};
S<bool>* p; // Uのデフォルト引数はこの時点でインスタンス化される
            // pの型はS<bool, int>*
(C++14以降)

注記

C++26より前、定数テンプレートパラメータは標準文書では非型テンプレートパラメータと呼ばれていました。この用語は P2841R6 / PR#7587 によって変更されました。

テンプレートパラメータでは、型制約は型パラメータと定数パラメータの両方に使用でき、 auto の有無によって異なります。

template<typename>
concept C = true;
template<C,     // type parameter 
         C auto // constant parameter
        >
struct S{};
S<int, 0> s;


(C++20以降)
機能テストマクロ 規格 機能
__cpp_nontype_template_parameter_auto 201606L (C++17) 定数テンプレートパラメータ の宣言に auto を使用
__cpp_nontype_template_args 201411L (C++17) すべての 定数テンプレート引数 に対する定数評価の許可
201911L (C++20) 定数テンプレートパラメータ におけるクラス型と浮動小数点型

#include <array>
#include <iostream>
#include <numeric>
// 単純な定数テンプレートパラメータ
template<int N>
struct S { int a[N]; };
template<const char*>
struct S2 {};
// 複雑な定数例
template
<
    char c,             // 整数型
    int (&ra)[5],       // オブジェクトへの左辺値参照(配列型)
    int (*pf)(int),     // 関数へのポインタ
    int (S<10>::*a)[10] // メンバオブジェクトへのポインタ(int[10]型)
>
struct Complicated
{
    // コンパイル時に選択された関数を呼び出し
    // 結果をコンパイル時に選択された配列に格納
    void foo(char base)
    {
        ra[4] = pf(c - base);
    }
};
//  S2<"fail"> s2;        // エラー: 文字列リテラルは使用不可
    char okay[] = "okay"; // リンケージを持つ静的オブジェクト
//  S2<&okay[0]> s3;      // エラー: 配列要素にリンケージなし
    S2<okay> s4;          // 動作する
int a[5];
int f(int n) { return n; }
// C++20: NTTPはリテラルクラス型で可能
template<std::array arr>
constexpr
auto sum() { return std::accumulate(arr.cbegin(), arr.cend(), 0); }
// C++20: クラステンプレート引数は呼び出しサイトで推論される
static_assert(sum<std::array<double, 8>{3, 1, 4, 1, 5, 9, 2, 6}>() == 31.0);
// C++20: NTTP引数推論とCTAD
static_assert(sum<std::array{2, 7, 1, 8, 2, 8}>() == 28);
int main()
{
    S<10> s; // s.aは10個のintの配列
    s.a[9] = 4;
    Complicated<'2', a, f, &S<10>::a> c;
    c.foo('0');
    std::cout << s.a[9] << a[4] << '\n';
}

出力:

42

不具合報告

以下の動作変更欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。

DR 適用バージョン 公開時の動作 修正後の動作
CWG 184 C++98 テンプレートテンプレートパラメータのテンプレートパラメータが
デフォルト引数を持つことを許可するかどうかが未規定
仕様を追加
CWG 1922 C++98 名前が注入クラス名であるクラステンプレートが以前の宣言の
デフォルト引数を使用できるかどうかが不明確
許可
CWG 2032 C++14 変数テンプレートについて、デフォルト引数を持つテンプレート
パラメータの後のテンプレートパラメータに対する制限がなかった
クラステンプレートおよび
エイリアステンプレートと
同じ制限を適用
CWG 2542 C++20 クロージャ型が構造的かどうかが不明確 構造的ではない
CWG 2845 C++20 クロージャ型は構造的ではなかった キャプチャなしの場合
構造的である