最終更新日時:
が更新

履歴 編集

テンプレートテンプレートパラメータに対するクラステンプレートパラメータ引数推論 [P3865R3](C++26)

このページはC++26に採用される見込みの言語機能の変更を解説しています。

のちのC++規格でさらに変更される場合があるため関連項目を参照してください。

概要

クラステンプレートのテンプレート引数推論 (CTAD, class template argument deduction) を、テンプレートテンプレートパラメータでも使用できるようにする。

C++23までは、テンプレートテンプレートパラメータに対してテンプレート引数推論を行えるかが規格上は規定されていなかった。実際にはC++23のstd::ranges::to()関数がこの機能に依存しており、すべての主要なコンパイラもテンプレートテンプレートパラメータのテンプレート引数推論を行えるよう実装されていた。C++26では、これを欠陥報告 (DR) として修正し、テンプレートテンプレートパラメータに対するクラステンプレートのテンプレート引数推論を正式に許可する。欠陥扱いであったため、この機能はC++23時点で使用できることが期待できる。

template <typename T>
struct C {
  C(T);
};

template <template <typename> class X>
void f()
{
  X x(1); // xの型はC<int>と推論される
}

template void f<C>();

仕様

テンプレートテンプレートパラメータに対するプレースホルダーの推論は、そのテンプレートテンプレートパラメータを、同じテンプレートパラメータをもつ「テンプレートテンプレート引数を表すエイリアステンプレート」に置き換えたものとして行われる。

これはエイリアステンプレートに対するCTADと同じ仕組みであり、単純にテンプレートテンプレート引数を代入する方式とは異なる。この方式によって、以下の2点が保証される。

  • テンプレートテンプレートパラメータに指定されたデフォルトテンプレート引数が尊重される
  • テンプレートテンプレートパラメータの名前では書けない型は推論されない (不適格となる)

テンプレートテンプレートパラメータの名前で書けない型は推論されない

template <typename... T>
struct C {
  C(T...);
};

template <template <typename> class X>
void f()
{
  X x1{1};    // OK: C<int>と推論される
  X x2{1, 2}; // エラー: C<int, int>はXの名前では書けないため、推論に失敗する
}

template void f<C>();

Xは型パラメータを1つだけとるため、C<int, int>のような型はXの名前では表現できない。そのためx2の推論は不適格となる。これはエイリアステンプレートに対するCTADと同様の「推論可能性 (deducible) 」の制約による。

デフォルトテンプレート引数が尊重される

template <typename T = int>
struct C {
  C(int);
};

template <template <typename = long> class X>
void f()
{
  X x{1}; // xの型はC<long>と推論される (Xのデフォルト引数longが使われる)
}

template void f<C>();

関連項目

参照