C++ Academy · レッスン

関数オブジェクトとファンクター

operator()を持つクラスを記述し、状態を持つ呼び出し可能オブジェクトを作ります。

レッスン 1/413 ステップ

「関数オブジェクトとファンクター」は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);     // false

STLアルゴリズムでファンクターを使う

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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 関数オブジェクトとファンクター
  2. ラムダの値キャプチャ、参照キャプチャ、mutable
  3. ジェネリックラムダとクロージャ(C++14)
  4. std::functionによる型消去可能な呼び出し可能オブジェクト
← C++ Academyに戻る