std::function
任意の呼び出し可能オブジェクトを格納します
「std::function」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。
std::functionとは
std::functionは、指定したシグネチャに一致する任意の呼び出し可能オブジェクトを保持できる、型消去ラッパーです。通常の関数、ラムダ、ファンクタ、バインド式などに対応します。
- 対象のシグネチャを指定して宣言します。
<functional>に定義されています。
#include <iostream>
#include <functional>
int add(int a, int b) { return a + b; }
int main() {
std::function<int(int, int)> f = add;
std::cout << f(2, 3) << '\n';
return 0;
}ラムダを格納する
通常の関数ポインタとは異なり、std::functionはキャプチャを含むラムダも問題なく格納できます。
#include <iostream>
#include <functional>
int main() {
int offset = 10;
std::function<int(int)> f = [offset](int x) { return x + offset; };
std::cout << f(5) << '\n';
return 0;
}ファンクタを格納する
ファンクタとは、operator()を持つオブジェクトです。std::functionはファンクタをラップし、呼び出されたときにそのoperatorを実行できます。
#include <iostream>
#include <functional>
struct Multiplier {
int factor;
int operator()(int x) const { return x * factor; }
};
int main() {
std::function<int(int)> f = Multiplier{3};
std::cout << f(4) << '\n';
return 0;
}対象を再代入する
1つのstd::function変数は、その有効期間中に異なる呼び出し可能オブジェクトを指せます。実行時に動作を切り替える場合に便利です。
#include <iostream>
#include <functional>
int main() {
std::function<int(int)> f = [](int x) { return x + 1; };
std::cout << f(10) << '\n';
f = [](int x) { return x * x; };
std::cout << f(10) << '\n';
return 0;
}空のstd::function
デフォルト構築されたstd::functionは何も保持しません。これを呼び出すとstd::bad_function_callがスローされるため、先に確認してください。
#include <iostream>
#include <functional>
int main() {
std::function<void()> f;
if (f) {
f();
} else {
std::cout << "empty\n";
}
return 0;
}パラメーターとして使用する
関数はstd::functionパラメーターを受け取ることで、一致する任意の呼び出し可能オブジェクトに対応でき、柔軟なAPIを作成できます。
#include <iostream>
#include <functional>
void repeat(int n, const std::function<void(int)>& action) {
for (int i = 0; i < n; ++i) action(i);
}
int main() {
repeat(3, [](int i) { std::cout << "step " << i << '\n'; });
return 0;
}コールバックを格納する
よくある用途は、クラスメンバーにコールバックを保持し、イベントが発生したときに後から呼び出せるようにすることです。
#include <iostream>
#include <functional>
struct Button {
std::function<void()> onClick;
void click() { if (onClick) onClick(); }
};
int main() {
Button b;
b.onClick = [] { std::cout << "clicked!\n"; };
b.click();
return 0;
}呼び出し可能オブジェクトのvector
同じ型として扱えるため、異なる呼び出し可能オブジェクトを1つのコンテナーに格納し、順番に呼び出せます。
#include <iostream>
#include <functional>
#include <vector>
int inc(int x) { return x + 1; }
int main() {
std::vector<std::function<int(int)>> ops;
ops.push_back(inc);
ops.push_back([](int x) { return x * 2; });
for (auto& op : ops) std::cout << op(10) << ' ';
std::cout << '\n';
return 0;
}型消去のコスト
std::functionはメモリを確保することがあり、間接呼び出しも追加されるため、直接呼び出しやテンプレート化された呼び出し可能オブジェクトより少し低速です。統一された格納方法が必要な場合に使用してください。
#include <iostream>
#include <functional>
int main() {
std::function<int()> f = [] { return 42; };
int total = 0;
for (int i = 0; i < 5; ++i) total += f();
std::cout << total << '\n';
return 0;
}std::functionを返す
ファクトリで設定済みの呼び出し可能オブジェクトを作成して返すと、呼び出し側でカスタマイズされた動作を取得できます。
#include <iostream>
#include <functional>
std::function<int(int)> adder(int n) {
return [n](int x) { return x + n; };
}
int main() {
auto add5 = adder(5);
std::cout << add5(10) << '\n';
return 0;
}関数ポインタと比較する
std::functionは状態を保持できるため関数ポインタより柔軟ですが、その分、パフォーマンスが少し低下し、メモリ確保が発生する可能性があります。
#include <iostream>
#include <functional>
int main() {
int base = 7;
std::function<int(int)> stateful = [base](int x) { return x + base; };
std::cout << "Stateful result: " << stateful(3) << '\n';
return 0;
}理解度チェック
std::functionについての理解度を確認してください。
まとめ
std::functionについて、次のことを学びました。
- 状態を持つラムダやファンクタを含め、シグネチャに一致する任意の呼び出し可能オブジェクトをラップします
- 再代入したり、コンテナーに格納したり、ファクトリから返したりできます
- 空の状態で呼び出すと
bad_function_callをスローします - 型消去による多少のオーバーヘッドがあります
次は、呼び出し可能オブジェクトの引数をあらかじめ設定するstd::bindを使用します。
よくある質問
「std::function」レッスンは無料ですか?
はい。「std::function」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。
「std::function」で何を学びますか?
任意の呼び出し可能オブジェクトを格納します ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C++ Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「std::function」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC++ Academyレッスンでコードを書いて実行できますか?
はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 関数ポインタ
- std::function
- std::bind
- 呼び出し可能オブジェクトの選択