このページはC++26に採用される見込みの言語機能の変更を解説しています。
のちのC++規格でさらに変更される場合があるため関連項目を参照してください。
概要
C++26では、テンプレートテンプレートパラメータとしてコンセプトおよび変数テンプレートを渡せるようになる。
C++23では、テンプレートテンプレートパラメータにはクラステンプレートまたはエイリアステンプレートのみを渡すことができた。変数テンプレートやコンセプトはテンプレートであるにもかかわらず、テンプレート引数として渡すことができなかった。
// コンセプトテンプレートパラメータの構文
template <
template <typename> concept C // コンセプトを受け取る
>
struct S {};
// 変数テンプレートテンプレートパラメータの構文
template <
template <typename> auto V // 変数テンプレートを受け取る
>
struct T {};
template <typename T>
concept MyConcept = true;
template <typename T>
constexpr auto MyVar = 42;
S<MyConcept> s; // OK (C++26)
T<MyVar> t; // OK (C++26)
仕様
コンセプトテンプレートパラメータ
テンプレートパラメータリストにおいて、conceptキーワードでコンセプトを受け取るパラメータを宣言できる。
template <template <typename> concept C>
void f();
コンセプトテンプレートパラメータは、制約としても使用できる。
// コンセプトアダプタの定義
template <typename T, template <typename> concept C>
concept decays_to = C<std::decay_t<T>>;
// 簡略構文での使用
template <decays_to<std::copyable> T>
auto f(T&& x);
変数テンプレートテンプレートパラメータ
テンプレートパラメータリストにおいて、autoキーワードで変数テンプレートを受け取るパラメータを宣言できる。
template <template <typename> auto V>
void g();
変数テンプレートは型が任意に特殊化できるため、autoは構文上のマーカーとして機能し、具体的な型名に置き換えることはできない。
// 述語を満たす要素を数える変数テンプレート
template <template <typename> auto pred, typename... Ts>
constexpr std::size_t count_if_v = (... + pred<Ts>);
この機能が必要になった背景・経緯
テンプレートテンプレートパラメータは、高階テンプレートやより柔軟な合成を可能にする機能である。クラステンプレートとエイリアステンプレートには対応していたが、変数テンプレートとコンセプトには対応しておらず、テンプレート機能の穴となっていた。
C++23でこれらをテンプレート引数として渡すためには、static constexpr bool valueメンバをもつクラステンプレートでラップする必要があった。しかし、このワークアラウンドには以下の問題があった:
- クラステンプレートのインスタンス化は変数テンプレートの参照よりもコンパイルコストが高い
- コンセプトの簡略構文 (terse syntax) や包摂 (subsumption) の恩恵を受けられない
- APIに不必要な複雑性を追加する
この提案は、P1985R3 Universal Template Parametersのサブセットとして、コンセプトと変数テンプレートに対するテンプレートテンプレートパラメータのサポートを先行して追加するものである。