std::functionによる型消去可能な呼び出し可能オブジェクト
std::functionの背後で型を消去し、スモールバッファ最適化を理解します。
「std::functionによる型消去可能な呼び出し可能オブジェクト」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。
問題: 多様な呼び出し可能オブジェクトを1つの型で扱う
各ラムダは一意の型を持ちます。各関数ポインターも異なる型です。これらのいずれでも保持できる1つの型、つまりstd::functionが必要です。
テンプレートパラメーター
std::function<Signature>には、戻り値の型とパラメーターの型を指定します。そのシグネチャで呼び出せるものなら、何でも受け取れます。
#include <functional>
std::function<int(int, int)> op;
op = [](int a, int b) { return a + b; };
std::cout << op(3, 4); // 7異なる呼び出し可能オブジェクトの格納
同じstd::function変数に、ラムダ、関数ポインター、ファンクターのいずれも格納できます。ただし、シグネチャが一致している必要があります。
std::function<int(int)> f;
f = [](int x) { return x * 2; }; // lambda
f = ::abs; // function pointer
f = std::negate<int>{}; // functor型消去
内部では、std::functionは型消去を使用します。任意の呼び出し可能オブジェクトを格納し、統一されたインターフェイスの背後に実際の型を隠します。多くの場合、小さなヒープ割り当てを伴って実装されます。
パフォーマンスコスト
std::function経由の呼び出しには、間接呼び出し(仮想関数に似ています)が伴います。ラムダの直接呼び出しより低速です。性能が重要な処理経路では避けてください。
std::functionを使う場合
次の場合に使用してください。
- コールバックをコンテナーやクラスメンバーに格納する
- 関数から呼び出し可能オブジェクトを返す
- プラグインシステムやイベントシステムを構築する
空のstd::function
デフォルト構築されたstd::functionは空です。呼び出すとstd::bad_function_callがスローされます。
std::function<void()> f;
if (f) f(); else std::cout << "no callback set";メンバー関数ポインター
std::bindでメンバー関数をバインドするか、ラムダでラップしてください。
struct Obj { void greet(int) {} };
Obj o;
std::function<void(int)> cb = [&](int n) { o.greet(n); };関数ポインターとの比較
関数ポインターは状態を保持できません。std::functionは保持できますが、間接呼び出しのコストがかかります。
テンプレートとの比較
呼び出し可能なパラメーターを持つテンプレートはコンパイル時に特殊化されるため、最も高速です。std::functionは実行時に解決されるため低速ですが、柔軟性があります。
template <typename F>
void run(F f) { f(); } // compile-time, no overhead
void run(std::function<void()> f) { f(); } // runtime, type erasureC++23のstd::function: std::function_ref
C++23ではstd::function_refが追加されました。これは呼び出し可能オブジェクトを所有しないビューです。存続期間が限定されている場合、ヒープ割り当てを回避できます。
代替手段
軽量な代替手段もあります。std::move_only_function(C++23)、tl::function_ref、folly::Functionなどです。要件に応じて選択してください。
クイックチェック
std::functionの主な欠点は何ですか。
まとめ
std::function<Signature>は、一致するシグネチャを持つ任意の呼び出し可能オブジェクトを格納します。コールバック、プラグイン、呼び出し可能オブジェクトに対する実行時ポリモーフィズムに便利ですが、間接呼び出しのコストがかかります。
よくある質問
「std::functionによる型消去可能な呼び出し可能オブジェクト」レッスンは無料ですか?
はい。「std::functionによる型消去可能な呼び出し可能オブジェクト」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。
「std::functionによる型消去可能な呼び出し可能オブジェクト」で何を学びますか?
std::functionの背後で型を消去し、スモールバッファ最適化を理解します。 ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C++ Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「std::functionによる型消去可能な呼び出し可能オブジェクト」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC++ Academyレッスンでコードを書いて実行できますか?
はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 関数オブジェクトとファンクター
- ラムダの値キャプチャ、参照キャプチャ、mutable
- ジェネリックラムダとクロージャ(C++14)
- std::functionによる型消去可能な呼び出し可能オブジェクト