Callable
コンセプトとstd::thread
に直面したstd::bind
とstd::invoke
について読んでいます。
cppreference でstd::invoke
について読みましたが、何を言っているのか理解できませんでした。ここに私の質問があります:std::invoke
、std::function
、std::bind
およびCallable
コンセプトとは何ですか?そして、それらの関係は何ですか?
_std::invoke
_は、呼び出し可能なものと、それを呼び出すための引数を取り、呼び出しを行います。 std::invoke( f, args... )
はf(args...)
を入力することのわずかな一般化であり、いくつかの追加のケースも処理します。
呼び出し可能なものには、関数ポインターまたは参照、メンバー関数ポインター、operator()
を持つオブジェクト、またはメンバーデータへのポインターが含まれます。
メンバーの場合、最初の引数はthis
として解釈されます。次に、残りの引数が_()
_に渡されます(member-to-member-data-caseを除く)。
INVOKEはC++標準の概念でした。 C++ 17は、それを直接行う_std::invoke
_を単に公開しました。他のメタプログラミングを行うときに役立つため、一部の標準ライブラリにはすでにINVOKEの実装が既にあり、公開は基本的に無料であり、一部は具体的なことでINVOKEについて話しやすくなるため、公開されたと思われます。
Callable
オブジェクトは、C++固有の詳細は別として、「呼び出すことができるもの」です。関数である必要はありません。C++には呼び出すことができる多くの型があり、表示される可能性のあるもの(読み取り:汎用コード)ごとにそれらを通過するのは問題が多く、繰り返しが多すぎます。
それが_std::invoke
_の目的です-呼び出すことができる汎用オブジェクト(C++ 17によれば、Callable
の概念を満たす)を簡単に呼び出すことができます。
簡単な例を考えてみましょう:
_void foo() { std::cout << "hello world\n"; };
template <bool b>
struct optionally_callable
{
std::enable_if_t<b> operator() () { std::cout << "hi again\n"; }
};
int main()
{
auto c = [] { std::cout << "hi from lambda\n" ;};
std::invoke(foo);
std::invoke(c);
auto o = optionally_callable<true>{};
//auto o2 = optionally_callable<false>{};
std::invoke(o);
}
_
_o2
_はnot callableです。つまり、std::is_invocable<decltype(o2)>::value
はfalse
です。