0Pricing
C++ Academy · レッスン

std::bind

呼び出し可能オブジェクトに引数を束縛します

「std::bind」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。

std::bindとは

std::bindは、既存の呼び出し可能オブジェクトの一部の引数を固定して、新しい呼び出し可能オブジェクトを作成します。これは部分適用と呼ばれます。

  • <functional>に定義されています。
  • 型が規定されていない呼び出し可能オブジェクトを返します。
#include <iostream>
#include <functional>

int add(int a, int b) { return a + b; }

int main() {
    auto add10 = std::bind(add, 10, 5);
    std::cout << add10() << '\n';
    return 0;
}

プレースホルダー

std::placeholders::_1のようなプレースホルダーは、バインドされたオブジェクトが呼び出されたときに後から指定する引数を示します。

#include <iostream>
#include <functional>

int add(int a, int b) { return a + b; }

int main() {
    using namespace std::placeholders;
    auto add10 = std::bind(add, 10, _1);
    std::cout << add10(7) << '\n';
    return 0;
}

引数の順序を変更する

プレースホルダーは任意の順序で配置できるため、呼び出し側が指定する引数の位置を入れ替えられます。

#include <iostream>
#include <functional>

int sub(int a, int b) { return a - b; }

int main() {
    using namespace std::placeholders;
    auto flipped = std::bind(sub, _2, _1);
    std::cout << flipped(3, 10) << '\n';
    return 0;
}

複数の引数をバインドする

複数の引数を一度に固定し、残りをプレースホルダーとして残せます。

#include <iostream>
#include <functional>

int volume(int l, int w, int h) { return l * w * h; }

int main() {
    using namespace std::placeholders;
    auto box = std::bind(volume, 2, _1, 5);
    std::cout << box(3) << '\n';
    return 0;
}

結果を格納する

std::bindが返すオブジェクトは、具体的で名前の付いた型を使用するためにstd::functionへ格納できます。

#include <iostream>
#include <functional>

int add(int a, int b) { return a + b; }

int main() {
    using namespace std::placeholders;
    std::function<int(int)> add100 = std::bind(add, 100, _1);
    std::cout << add100(1) << '\n';
    return 0;
}

メンバー関数をバインドする

std::bindでは、メンバーポインタとthisに対応するオブジェクト(またはプレースホルダー)を渡して、メンバー関数を対象にできます。

#include <iostream>
#include <functional>

struct Counter {
    int add(int x) { return value += x; }
    int value = 0;
};

int main() {
    using namespace std::placeholders;
    Counter c;
    auto bump = std::bind(&Counter::add, &c, _1);
    std::cout << bump(5) << ' ' << bump(3) << '\n';
    return 0;
}

値渡しと参照渡しによるバインド

バインドされた引数はデフォルトでコピーされます。引数をstd::refでラップすると参照でバインドされ、変更が反映されます。

#include <iostream>
#include <functional>

void addTo(int& target, int amount) { target += amount; }

int main() {
    using namespace std::placeholders;
    int total = 0;
    auto acc = std::bind(addTo, std::ref(total), _1);
    acc(5);
    acc(10);
    std::cout << total << '\n';
    return 0;
}

アルゴリズムでバインドされた呼び出し可能オブジェクトを使用する

バインドされた呼び出し可能オブジェクトは、標準アルゴリズムの述語や操作として使用できます。

#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>

bool greaterThan(int x, int limit) { return x > limit; }

int main() {
    using namespace std::placeholders;
    std::vector<int> v = {1, 5, 8, 2, 9};
    auto over4 = std::bind(greaterThan, _1, 4);
    std::cout << std::count_if(v.begin(), v.end(), over4) << '\n';
    return 0;
}

bindをネストする

バインド式は組み合わせられますが、すぐに読みにくくなります。各プレースホルダーは、最終的に呼び出す側の引数を参照します。

#include <iostream>
#include <functional>

int add(int a, int b) { return a + b; }
int times(int a, int b) { return a * b; }

int main() {
    using namespace std::placeholders;
    auto f = std::bind(add, std::bind(times, 2, _1), 3);
    std::cout << f(5) << '\n';
    return 0;
}

余分な引数を無視する

バインドされた呼び出しで一部のプレースホルダーしか使用しない場合、呼び出し時に渡された余分な引数は単純に無視されます。

#include <iostream>
#include <functional>

int show(int a) { return a; }

int main() {
    using namespace std::placeholders;
    auto f = std::bind(show, _1);
    std::cout << f(42, 99, 100) << '\n';
    return 0;
}

ラムダのほうが明確な場合

現代のC++では、std::bindよりラムダが選ばれることがよくあります。ラムダのほうが読みやすく、コンパイラーによる最適化も優れているためです。

#include <iostream>
#include <functional>

int add(int a, int b) { return a + b; }

int main() {
    auto add10 = [](int x) { return add(10, x); };
    std::cout << add10(5) << '\n';
    return 0;
}

理解度チェック

プレースホルダーについての理解度を確認してください。

まとめ

std::bindの動作について学びました。

  • 一部の引数を固定し、残りには_1や_2などのプレースホルダーを使用します
  • 引数の順序を変更したり、メンバー関数をバインドしたり、std::refを使用したりできます
  • 結果はstd::functionに格納してアルゴリズムで使用できます
  • 現代のC++では、ラムダのほうが明確なことがよくあります

次は、ラムダ、bind、関数ポインタを比較し、適切なツールを選びます。

よくある質問

「std::bind」レッスンは無料ですか?

はい。「std::bind」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。

「std::bind」で何を学びますか?

呼び出し可能オブジェクトに引数を束縛します ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C++ Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「std::bind」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC++ Academyレッスンでコードを書いて実行できますか?

はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

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

  1. 関数ポインタ
  2. std::function
  3. std::bind
  4. 呼び出し可能オブジェクトの選択
← C++ Academyに戻る