次期C++2a(C++20)標準規格に向けて採択された、コンセプト(concept)関連の短縮構文についてメモ。C++コンセプト概略ついては id:yohhoy:20170904 を参照のこと。
本記事の内容は P1141R2 Yet another approach for constrained declarations に基づく。
要約:
- autoキーワードによる関数テンプレート定義が可能。“
template
-less Function Template” - 現行autoキーワードを用いた型推論にて、コンセプト名による制約付けが可能。
関数テンプレートパラメータT
へのコンセプトC
指定では、下記構文のいずれかを用いて制約(constraint)を指定できる。短縮関数テンプレート(abbreviated function template)構文が新たに追加され、templateキーワードを用いない関数テンプレート定義が可能となる。(→id:yohhoy:20150303)
// C++2a // 型パラメータTに対するコンセプトC template <typename T> concept C = /*...*/; // A) 制約付きパラメータ(constrained-parameter)による制約 template <C T> void func(T arg); // B) requires節(requires-clause)による制約 template <typename T> requires C<T> void func(T arg); // C) 末尾requires節(trailing requires-clause)による制約 template <typename T> void func(T arg) requires C<T>; // D) ★短縮関数テンプレート(abbreviated function template)構文 void func(C auto arg); // D') ★コンセプト制約なし短縮関数テンプレート void func1(auto arg);
従来からパラメータ型宣言でautoキーワードを利用していたジェネリックラムダ(generic lambda)でも同様の構文となる。
// C++14以降: ジェネリックラムダ auto lm0 = [](auto arg) { /*...*/ }; // C++2a: ジェネリックラムダのテンプレート構文 auto lm0 = []<typename T>(T arg) { /*...*/ }; // C++2a: テンプレートパラメータ型制約付きジェネリックラムダ(4パターン) auto lm1 = []<C T>(T arg) { /*...*/ }; auto lm1 = []<typename T> requires C<T> (T arg) { /*...*/ }; auto lm1 = []<typename T> (T arg) requires C<T> { /*...*/ }; auto lm1 = [](C auto arg) { /*...*/ }; // ★P1141R2で導入
autoキーワードを用いた関数の戻り値型推論や変数型推論においても、推論される型に対してコンセプトC
による制約付けが行える。いずれもautoキーワードは必須であり、コンセプト名のみ(C f2();
やC v2;
)ではill-formedとなる。
// 戻り値型に制約なし auto f0() { return /*...*/; } decltype(auto) h0() { return /*...*/; } // 変数型に制約なし auto v0 = f0(); // C++2a: 戻り値型はコンセプトCを満たすべき C auto f1() { return /*...*/; } C decltype(auto) h1() { return /*...*/; } // C++2a: 変数型はコンセプトCを満たすべき C auto v1 = f1();
関連URL