std::function の表記は、関数ポインターと比較すると非常に優れています。ただし、それ以外に、ポインターに置き換えられなかったユースケースは見つかりません。では、関数ポインターの構文糖衣にすぎないのでしょうか?
2 に答える
std::function<>
任意のタイプの callable objectをカプセル化する可能性を提供します。これは、関数ポインターでは実行できないことです (ただし、非キャプチャーラムダを関数ポインターに変換できることは事実です)。
達成できる柔軟性の種類を理解するために、次のことを行います。
#include <functional>
#include <iostream>
#include <vector>
// A functor... (could even have state!)
struct X
{
void operator () () { std::cout << "Functor!" << std::endl; }
};
// A regular function...
void bar()
{
std::cout << "Function" << std::endl;
}
// A regular function with one argument that will be bound...
void foo(int x)
{
std::cout << "Bound Function " << x << "!" << std::endl;
}
int main()
{
// Heterogenous collection of callable objects
std::vector<std::function<void()>> functions;
// Fill in the container...
functions.push_back(X());
functions.push_back(bar);
functions.push_back(std::bind(foo, 42));
// And a add a lambda defined in-place as well...
functions.push_back([] () { std::cout << "Lambda!" << std::endl; });
// Now call them all!
for (auto& f : functions)
{
f(); // Same interface for all kinds of callable object...
}
}
いつものように、ここで実際の例を見てください。とりわけ、これによりCommand Patternを実現できます。
std::function
あらゆる種類の呼び出し可能なオブジェクトを表すように設計されています。関数ポインターでは表現できない呼び出し可能なオブジェクトがたくさんあります。
ファンクタ:
struct foo { bool operator()(int x) { return x > 5; } }; bool (*f1)(int) = foo(); // Error std::function<bool(int)> f2 = foo(); // Okay
のインスタンスを作成して関数ポインター
foo
に格納することはできません。bool(*)(int)
lambda-captureを使用したラムダ:
bool (*f1)(int) = [&](int x) { return x > y; }; // Error std::function<bool(int)> f2 = [&](int x) { return x > y; }; // Okay
ただし、キャプチャのないラムダは関数ポインターに変換できます。
ラムダ キャプチャのないラムダ式のクロージャ型には、クロージャ型の関数呼び出し演算子と同じパラメーターと戻り値の型を持つ関数へのポインターへの public 非仮想非明示的な const 変換関数があります。この変換関数によって返される値は、呼び出されたときにクロージャー型の関数呼び出し演算子を呼び出すのと同じ効果を持つ関数のアドレスでなければなりません。
実装定義の呼び出し可能な戻り値:
bool foo(int x, int y) { return x > y; }; bool (*f1)(int) = std::bind(&foo, std::placeholders::_1, 5); // Error (probably) std::function<bool(int)> f2 = std::bind(&foo, std::placeholders::_1, 5); // Okay
std::bind
の戻り値は、実装定義の呼び出し可能オブジェクトです。そのオブジェクトのタイプではなく、そのオブジェクトの使用方法のみが標準で指定されています。