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

履歴 編集

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

概要

型しか現れない文脈では、依存名を解決するための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を省略できるようになった。

参照