このページはC++20に採用された言語機能の変更を解説しています。
のちのC++規格でさらに変更される場合があるため関連項目を参照してください。
概要
C++17で導入されたクラステンプレートのテンプレート引数推論は、コンストラクタ引数からテンプレート引数を推論するものであった。しかし、そのクラステンプレートのエイリアステンプレートを定義した場合に、エイリアステンプレートの変数定義からはクラステンプレートのテンプレート引数を推論できない問題があった。
C++20では、エイリアステンプレートからでもコンストラクタ引数からクラステンプレート引数を推論できるようになる。
template <class T>
struct Point {
T x;
T y;
Point(T x_, T y_)
: x(x_), y(y_) {}
};
template <class T>
using MyPoint = Point<T>;
MyPoint p1{3.0, 4.0}; // C++17:NG C++20:OK
エイリアステンプレート側で制約を課した場合:
#include <concepts>
#include <type_traits>
template <class T, class U>
struct C {
C(T, U); // #1
};
template <class T, class U>
C(T, U) -> C<T, std::type_identity_t<U>>; // #2
// 2つのテンプレート引数を同じ型、かつポインタ型に限定する
template <class V>
using A = C<V*, V*>;
// 2つのテンプレート引数を同じ型、かつ整数のポインタ型に限定する
template <std::integral W>
using B = A<W>;
int i{};
double d{};
A a1(&i, &i); // A<int>に推論される
A a2(i, i); // エラー! iからV*を推論できない (ポインタ型でないといけない)
A a3(&i, &d); // エラー!
// #1: (int *, double *)から(V*, V*)を推論できない
// #2: C<int *, double *>からA<V>を推論できない
B b1(&i, &i); // B<int>に推論される
B b2(&d, &d); // エラー! C<double*, double*>からB<W>を推論できない
// (整数のポインタ型でないといけない)