最終更新日時(UTC):
が更新

履歴 編集

型の文脈でtypenameの省略を許可 [P0634R3](C++20)

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

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

概要

型しか現れない文脈では、依存名を解決するためのtypenameキーワードを省略できるようにする。

仕様

修飾名は、以下の条件を満たすときに型名とみなされる。

  • 型しか現れない文脈にある
  • 以下の宣言における型指定子である
    • 名前空間スコープの単純宣言(≒変数宣言または構造化束縛宣言)または関数定義
    • メンバ宣言
    • メンバ宣言の中の引数宣言(デフォルト引数に現れる場合を除く)
    • 識別子が修飾名である関数または関数テンプレートの引数宣言(デフォルト引数に現れる場合を除く)
    • ラムダ式またはrequires式の引数宣言(デフォルト引数に現れる場合を除く)
    • 非型テンプレートパラメーターの宣言

// 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を省略できるようになった。

参照