【C++】std::function の使い方 | あらゆる「呼び出し可能オブジェクト」を保持する方法

目次

はじめに

C++には、「呼び出し可能 (callable)」なものがいくつかあります。

  • 通常の関数
  • ラムダ式
  • ()演算子をオーバーロードした関数オブジェクト(ファンクタ)

これらはそれぞれ型が異なるため、通常は同じ変数に代入することはできません。しかし、<functional>ヘッダーで提供される std::function を使えば、これらの異なる種類の「呼び出し可能なもの」を、統一された一つの型として扱うことができます。

std::function は、後から実行する処理を切り替えたり、コールバック関数を登録したりする場面で、非常に強力なツールとなります。


【前提】C++11とは?

C++11は、2011年に正式化されたC++言語のメジャーアップデート版です。std::function やラムダ式はC++11で導入されたため、利用するにはC++11以降に対応したコンパイラが必要です。


std::function を使ったサンプルコード

このコードは、同じシグネチャ(intを2つ受け取りintを返す)を持つ、3種類の異なる「呼び出し可能なもの」を、全て std::function 型の変数に代入して実行します。

完成コード

#include <iostream>
#include <functional> // std::function
#include <string>

using namespace std;

// 1. 関数オブジェクト(ファンクタ)
struct Adder {
    int operator()(int a, int b) const {
        return a + b;
    }
};

// 2. 通常の関数
int multiplier(int a, int b) {
    return a * b;
}

int main() {
    // std::functionの型を定義: <戻り値の型(引数の型1, 引数の型2)>
    function<int(int, int)> operation;

    // --- a. 関数オブジェクトを代入 ---
    operation = Adder{};
    cout << "関数オブジェクトの結果: " << operation(10, 5) << endl;

    // --- b. 通常の関数を代入 ---
    operation = multiplier;
    cout << "通常の関数の結果: " << operation(10, 5) << endl;

    // --- c. ラムダ式を代入 ---
    operation = [](int a, int b) {
        return a - b;
    };
    cout << "ラムダ式の結果: " << operation(10, 5) << endl;

    return 0;
}

実行結果

関数オブジェクトの結果: 15
通常の関数の結果: 50
ラムダ式の結果: 5

コードの解説

function<int(int, int)> operation;

これが std::function の宣言です。

  • std::function< ... >: < >の中に、保持したい関数のシグネチャ(戻り値と引数の型)を記述します。
  • int(int, int): これは「int型の引数を2つ取り、int型の値を返す」というシグネチャを表しています。

この operation という変数には、上記のシグネチャに一致するものであれば、関数オブジェクト、通常の関数、ラムダ式のいずれでも代入することが可能になります。

operation = Adder{};

Adder構造体は、operator() を実装しているため「関数オブジェクト」として振る舞います。そのシグネ-チャが int(int, int) と一致するため、operation に代入できます。

operation = multiplier;

multiplier は、シグネチャが一致する通常の関数です。これも operation に代入できます。

operation = [](int a, int b) { ... };

ラムダ式も、シグネチャが一致すれば operation に代入できます。

operation(10, 5)

std::function 変数は、まるで本物の関数であるかのように、() を使って中の処理を呼び出すことができます。


まとめ

今回は、C++11の std::function を使って、様々な「呼び出し可能なもの」を統一的に扱う方法を解説しました。

  • std::function<戻り値(引数...)> で、関数のシグネチャを指定して変数を宣言する。
  • 宣言した変数には、シグネチャが一致する関数、関数オブジェクト、ラムダ式などを代入できる。

std::function は、実行時に処理内容を動的に切り替えたい場合や、様々な種類のコールバック関数を受け入れる必要がある場合に、プログラムの柔軟性を大幅に向上させます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次