以下のようなコンセプトを書いた場合、result_typeの型はテンプレートと同様の
あらゆる型を受け取れる型になります。
このresult_typeは関連型(Associated Type)といいます。
auto concept Function<class F> { typename result_type; result_type operator()(F&); }
Functionコンセプトを以下のような関数オブジェクトに使用した場合には
struct functor { int operator()() const; };
Functionのresult_typeはintになります。
template <Function F> F::result_type foo(F f) { return f(); } int result = foo(functor());
ここまででわかるように、関連型(Associated Type)を使用することで
型を直接指定することなく推論してくれるので、result_typeを持っていない
関数オブジェクトからでもresult_type(戻り値の型)を取得することができます。
ちなみに、コンセプトによって、それが型だということがテンプレートのインスタンス化の前にわかるので、
関連型を使用する際には頭にtypenameを付ける必要はありません。
(typename F::result_typeじゃなくてF::result_typeでOK)
また、関連型に対する要件も指定することができるので
関連型にもコンセプトの厳格な型チェックを適用することができます。
auto concept Function<class F> { typename result_type; requires std::Returnable<result_type>; result_type operator()(F&); }