このページはC++29に採用された言語機能の変更を解説しています。
のちのC++規格でさらに変更される場合があるため関連項目を参照してください。
概要
C++29では、C++26で導入されたパラメータパックへの添字アクセスを、テンプレートテンプレートパラメータのパック(テンプレート名のパック)に対しても使用できるようになる。
template <template <typename> typename... TT>
struct S {
template <typename T>
using First = TT...[0]<T>;
};
TT...[N]はテンプレート名として扱われ、テンプレート名を書けるあらゆる場所で使用できる。クラステンプレートのテンプレートテンプレートパラメータに加えて、C++26で導入された変数テンプレート・コンセプトのテンプレートテンプレートパラメータのパックにも適用できる。
仕様
- 添字アクセス
P...[N]のPはパックを表すテンプレート名であること - 添字
Nはstd::size_t型へ変換された定数式であり、その値Vは0 <= V < sizeof...(P)の範囲であること。P...[V]は、パックのV番目のテンプレート名を表す P...[N]自体はパック展開であり、パターンはテンプレート名であるP...[N]がクラステンプレートやエイリアステンプレートを表す場合は、クラステンプレートのテンプレート引数推論にも使用できる
例
#include <iostream>
#include <list>
#include <vector>
template <template <class> class... TT>
struct S {
// パックTTの先頭のテンプレートを、テンプレート名として使用する
template <class T>
using First = TT...[0]<T>;
};
int main()
{
// TT...[0]はstd::vectorを指すため、First<int>はstd::vector<int>
S<std::vector, std::list>::First<int> v = {1, 2, 3};
std::cout << v[1] << std::endl;
}
出力
2
この機能が必要になった背景・経緯
C++26のパラメータパックへの添字アクセス (P2662R3) は、型のパックと式のパックのみを対象としており、テンプレート名のパックには使用できなかった。設計としてはすべてのパックに添字アクセスできることを意図していたが、当時審議中だったコンセプトと変数テンプレートをテンプレート引数として渡せるようにする提案 (P2841) などとの相互作用が明確でなかったため、テンプレート名のパックは見送られていた。
P2841がテンプレート名のパックへの添字アクセスの設計に影響しないことが確認されたため、本提案によってパック添字アクセスの設計が完成された。