関数オブジェクトとファンクター
operator()を持つクラスを記述し、状態を持つ呼び出し可能オブジェクトを作ります。
「関数オブジェクトとファンクター」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。
ファンクターとは
ファンクター(関数オブジェクト)とは、operator()をオーバーロードしたクラスです。インスタンスは関数のように呼び出せます。
struct Square {
int operator()(int x) const { return x * x; }
};
Square sq;
std::cout << sq(5); // 25単なる関数ではいけない理由
ファンクターは状態を保持します。通常の関数は保持しません。状態があることで、設定、カウント、状態を持つコールバックを実現できます。
struct Counter {
int count = 0;
int operator()(int x) { ++count; return x; }
};
Counter c;
c(10); c(20); c(30);
std::cout << c.count; // 3設定可能な振る舞い
設定をファンクターのメンバーに格納します。同じファンクター型を、さまざまなパラメーターセットで使用できます。
struct GreaterThan {
int threshold;
bool operator()(int x) const { return x > threshold; }
};
GreaterThan over10{10};
over10(15); // true
over10(5); // falseSTLアルゴリズムでファンクターを使う
STLアルゴリズムは、ファンクター、ラムダ、関数ポインターなど、呼び出し可能なものなら何でも受け取れます。
std::vector<int> v = {1, 11, 5, 99, 8};
auto it = std::find_if(v.begin(), v.end(), GreaterThan{10});
std::cout << *it; // 11<functional>の定義済みファンクター
標準ライブラリには、すぐに使えるファンクターとして、std::plus、std::less、std::equal_to、std::negateなどが用意されています。
#include <functional>
std::vector<int> v = {3, 1, 4, 1, 5};
std::sort(v.begin(), v.end(), std::greater<int>{});
// sorted descendingファンクターと関数ポインターの違い
ファンクターはoperator()が直接呼び出されるため、通常はより適切にインライン化されます。関数ポインターは柔軟性が高い一方で、間接呼び出しになります。
テンプレートパラメーターとしてのファンクター
多くのSTLコンテナーやアルゴリズムは、テンプレートパラメーターとしてファンクターを受け取ります。たとえば、setの比較関数、ハッシュ関数、アロケーターなどです。
std::set<int, std::greater<int>> s = {1, 2, 3};
// s iterates in descending order: 3, 2, 1ラムダはファンクター
コンパイラーは、ラムダごとにoperator()を持つ一意のクラスを生成します。ラムダは、ファンクターに対する構文糖です。
ファンクターを記述する場合
次の場合は、手書きのファンクターを使用してください。
- 同じロジックを多くの場所で使う(名前を付けられる)
- パブリックAPIの一部である
- 特定の振る舞いを持つコピー/ムーブ構築が必要である
代わりにラムダを使う場合
一度しか使わない場合は、ラムダのほうが短く明確です。再利用する振る舞いには、名前付きファンクターのほうが可読性を高められます。
合成可能性
std::bindを使うか、より現代的にはラムダを合成して、ファンクターを組み合わせられます。Boostなどの関数型ライブラリにもコンビネーターが用意されています。
クイックチェック
通常の関数と比べたとき、ファンクターの主な機能は何ですか。
まとめ
ファンクターはoperator()を持つクラスです。状態を保持し、STLアルゴリズムと統合でき、ラムダの基盤にもなります。再利用する振る舞いには名前付きファンクターを、一度だけ使うロジックにはラムダを使用してください。
AI チューターと学ぶ C++ — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 51
- レッスン
- 203
よくある質問
「関数オブジェクトとファンクター」レッスンは無料ですか?
はい。「関数オブジェクトとファンクター」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。
「関数オブジェクトとファンクター」で何を学びますか?
operator()を持つクラスを記述し、状態を持つ呼び出し可能オブジェクトを作ります。 ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C++ Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「関数オブジェクトとファンクター」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC++ Academyレッスンでコードを書いて実行できますか?
はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。