このページはC++20に採用された言語機能の変更を解説しています。
のちのC++規格でさらに変更される場合があるため関連項目を参照してください。
概要
型しか現れない文脈では、依存名を解決するためのtypename
キーワードを省略できるようにする。
仕様
修飾名は、以下の条件を満たすときに型名とみなされる。
- 型しか現れない文脈にある
- new演算子に指定する型名
- エイリアス宣言またはエイリアステンプレート宣言に現れる型名
- 後置の戻り値型
- テンプレート型引数のデフォルト引数
static_cast
、const_cast
、reinterpret_cast
、dynamic_cast
の型名
- 以下の宣言における型指定子である
// P0634R3より引用
template<class T> T::R f(); // OK, グローバルスコープにおける関数の戻り値
template<class T> void f(T::R); // Ill-formed, void型の変数テンプレートの宣言
template<class T> struct S {
// クラススコープ
using Ptr = PtrTraits<T>::Ptr; // OK, エイリアス宣言
T::R f(T::P p) { // OK, メンバ宣言、およびメンバ宣言における仮引数宣言
return static_cast<T::R>(p); // OK, static_castの型名
}
auto g() -> S<T*>::Ptr; // OK, 後置戻り値型
};
template<typename T> void f() {
// ブロックスコープ
void (*pf)(T::X); // T::Xで初期化されるvoid*型の変数pf
void g(T::X); // エラー: void型の変数宣言
}
例
#include <iostream>
#include <vector>
template<typename T>
auto Begin(const T& t) -> T::const_iterator {
return t.begin();
}
int main()
{
std::vector v = {1, 2, 3, 4, 5};
std::cout << *Begin(v) << std::endl;
}
出力
1
この機能が必要になった背景・経緯
以前から基底クラスの指定ではtypename
を省略することができた。
template<class T>
struct Derived: T::Base // typename不要
{};
しかし、他にも型しか現れない文脈は存在するので、それらでもtypename
を省略できるようになった。