名前空間
変種
操作

std::bind

提供: cppreference.com
< cpp‎ | utility‎ | functional
 
 
ユーティリティライブラリ
汎用ユーティリティ
日付と時間
関数オブジェクト
書式化ライブラリ (C++20)
(C++11)
関係演算子 (C++20で非推奨)
整数比較関数
(C++20)
スワップと型操作
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
一般的な語彙の型
(C++11)
(C++17)
(C++17)
(C++17)
(C++17)

初等文字列変換
(C++17)
(C++17)
 
関数オブジェクト
関数ラッパー
(C++11)
(C++11)
関数の部分適用
(C++20)
bind
(C++11)
関数呼び出し
(C++17)
恒等関数オブジェクト
(C++20)
参照ラッパー
(C++11)(C++11)
演算子ラッパー
否定子
(C++17)
検索子
制約付き比較子
古いバインダとアダプタ
(C++17未満)
(C++17未満)
(C++17未満)
(C++17未満)
(C++17未満)(C++17未満)(C++17未満)(C++17未満)
(C++20未満)
(C++20未満)
(C++17未満)(C++17未満)
(C++17未満)(C++17未満)

(C++17未満)
(C++17未満)(C++17未満)(C++17未満)(C++17未満)
(C++20未満)
(C++20未満)
 
ヘッダ <functional> で定義
(1)
template< class F, class... Args >
/*unspecified*/ bind( F&& f, Args&&... args );
(C++11以上)
(C++20未満)
template< class F, class... Args >
constexpr /*unspecified*/ bind( F&& f, Args&&... args );
(C++20以上)
(2)
template< class R, class F, class... Args >
/*unspecified*/ bind( F&& f, Args&&... args );
(C++11以上)
(C++20未満)
template< class R, class F, class... Args >
constexpr /*unspecified*/ bind( F&& f, Args&&... args );
(C++20以上)

関数テンプレート bindf に対する転送呼び出しラッパーを生成します。 このラッパーの呼び出しは args に束縛された引数のいくつかを使用して f を呼ぶことと同等です。

目次

[編集] 引数

f - いくつかの引数に束縛される Callable なオブジェクト (関数オブジェクト、関数ポインタ、関数参照、メンバ関数ポインタまたはデータメンバポインタ)
args - 名前空間 std::placeholders のプレースホルダー _1, _2, _3... で置き換えた未束縛引数を持つ、束縛する引数のリスト

[編集] 戻り値

std::is_bind_expression<T>::value == true である未規定な型 T の関数オブジェクト。 以下のメンバを持ちます。

std::bind戻り値の型

メンバオブジェクト

std::bind の戻り値の型は std::forward<F>(f) から構築された std::decay<F>::type 型のメンバオブジェクト、および args... のそれぞれについて同様に std::forward<Arg_i>(arg_i) から構築された std::decay<Arg_i>::type 型のオブジェクトをひとつずつ保持します。

コンストラクタ

std::bind の戻り値の型は、そのすべての (上で規定されている) メンバオブジェクトが CopyConstructible であれば CopyConstructible であり、そうでなければ MoveConstructible です。 この型は以下のメンバを定義します。

メンバ型 result_type

1) (C++17で非推奨) F が関数ポインタまたはメンバ関数ポインタであれば、 result_typeF の戻り値の型です。 F がネストした typedef result_type を持つクラス型であれば、 result_typeF::result_type です。 そうでなければ result_type は定義されません。

2) (C++17で非推奨) result_type は正確に R です。

(C++20未満)

メンバ関数 operator()

bind の以前の呼び出しによって取得されたオブジェクト g が関数呼び出し式 g(u1, u2, ... uM) で呼ばれた場合、 std::invoke(fd, std::forward<V1>(v1), std::forward<V2>(v2), ..., std::forward<VN>(vN)) によって行われたかのように、格納されているオブジェクトの呼び出しが行われます。 ただし fdstd::decay_t<F> 型の値であり、束縛引数 v1, v2, ..., vN の値および型は以下のように決定されます。

  • 格納されている引数 argstd::reference_wrapper<T> 型の場合 (例えば bind の呼び出しで std::ref または std::cref が使用された)、上の std::invoke 呼び出しの引数 vnarg.get() であり、型 VnT& です。 格納されている引数は呼び出された関数オブジェクトに参照渡しされます。
  • 格納されている引数 argstd::is_bind_expression<T>::value == true であるような型 T の場合 (例えば別の bind 式が bind の呼び出しに直接渡された)、 bind は関数合成を行います。 bind 部分式が返す関数オブジェクトを渡す代わりに、その部分式が先行して呼び出され、その戻り値が外側の呼び出し可能なオブジェクトに渡されます。 bind 部分式が何らかのプレースホルダー引数を持っている場合、それらは外側の bind と共有されます (u1, u2, ... から取り出されます)。 具体的には、上の std::invoke 呼び出しの引数 vnarg(std::forward<Uj>(uj)...) であり、その型 Vnstd::result_of_t<T cv &(Uj&&...)>&& です (cv 修飾は g のものと同じです)。
  • 格納されている引数 argstd::is_placeholder<T>::value != 0 であるような型 T の場合 (std::placeholders::_1, _2, _3, ... のようなプレースホルダーが bind の呼び出しの引数として使用された)、そのプレースホルダーの表す引数 (_1 の場合は u1_2 の場合は u2、など) が呼び出し可能なオブジェクトに渡されます。 上の std::invoke 呼び出しの引数 vnstd::forward<Uj>(uj) であり、対応する型 VnUj&& です。
  • そうでなければ、普通の格納されている引数 arg が呼び出し可能なオブジェクトに左辺値引数として渡されます。 上の std::invoke 呼び出しの引数 vn は単純に arg であり、対応する型 VnT cv & です。 ただし cv は g のものと同じ cv 修飾です。

g() の呼び出しに供給された引数のいくつかが g に格納されているいずれのプレースホルダーによってもマッチされない場合、未使用の引数は評価され破棄されます。

g が volatile 修飾されている場合 (つまり cv 修飾子が volatile または const volatile のいずれかの場合)、動作は未定義です。

[編集] 例外

std::forward<F>(f) からの std::decay<F>::type の構築が例外を投げる場合、または std::decay<Arg_i>::type に対する対応する std::forward<Arg_i>(arg_i) からのコンストラクタのいずれかが例外を投げる場合にのみ、例外を投げます。 ただし Arg_iArgs... args のi番目の型で arg_i はi番目の引数です。

[編集] ノート

Callable で説明されているように、非静的メンバ関数ポインタまたは非静的データメンバポインタを呼び出すとき、最初の引数はアクセスされるメンバを持つオブジェクトへの参照またはポインタ (std::shared_ptr および std::unique_ptr のようなスマートポインタも含みます) でなければなりません。

束縛される引数はコピーまたはムーブされます。 std::ref または std::cref でラップされていなければ、参照渡しされることはありません。

同じ bind 式で複数のプレースホルダーを使用する (例えば _1 を複数回使用する) ことができますが、結果は対応する引数 (u1) が左辺値またはムーブ可能でない右辺値である場合にのみ well-defined です。

[編集]

#include <random>
#include <iostream>
#include <memory>
#include <functional>
 
void f(int n1, int n2, int n3, const int& n4, int n5)
{
    std::cout << n1 << ' ' << n2 << ' ' << n3 << ' ' << n4 << ' ' << n5 << '\n';
}
 
int g(int n1)
{
    return n1;
}
 
struct Foo {
    void print_sum(int n1, int n2)
    {
        std::cout << n1+n2 << '\n';
    }
    int data = 10;
};
 
int main()
{
    using namespace std::placeholders;  // _1, _2, _3... のため。
 
    // 引数の順序変更と参照渡しをデモンストレーションします。
    int n = 7;
    // (_1 と _2 は std::placeholders のもので、 f1 に渡される未来の引数を表します)
    auto f1 = std::bind(f, _2, 42, _1, std::cref(n), n);
    n = 10;
    f1(1, 2, 1001); // 1 は _1 によって束縛され、 2 は _2 によって束縛され、 1001 は未使用です。
                    // f(2, 42, 1, n, 7) の呼び出しを行います。
 
    // プレースホルダを共有するネストした bind 部分式。
    auto f2 = std::bind(f, _3, std::bind(g, _3), _3, 4, 5);
    f2(10, 11, 12); // f(12, g(12), 12, 4, 5); の呼び出しを行います。
 
    // 一般的なユースケース: 乱数エンジンに分布を束縛します。
    std::default_random_engine e;
    std::uniform_int_distribution<> d(0, 10);
    auto rnd = std::bind(d, e); // e のコピーが rnd に格納されます。
    for(int n=0; n<10; ++n)
        std::cout << rnd() << ' ';
    std::cout << '\n';
 
    // メンバ関数に引数を束縛します。
    Foo foo;
    auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1);
    f3(5);
 
    // データメンバにポインタを束縛します。
    auto f4 = std::bind(&Foo::data, _1);
    std::cout << f4(foo) << '\n';
 
    // 参照先のオブジェクトのメンバを呼ぶためにスマートポインタを使用することもできます。
    std::cout << f4(std::make_shared<Foo>(foo)) << '\n'
              << f4(std::make_unique<Foo>(foo)) << '\n';
}

出力:

2 42 1 10 7
12 12 12 4 5
1 5 0 2 0 8 2 2 10 8
100
10
10
10

[編集] 関連項目

可変個の引数を順番通りに関数オブジェクトに束縛します
(関数テンプレート) [edit]
std::bind 式におけるバインドされない引数のためのプレースホルダ
(定数) [edit]
(C++11)
メンバポインタから関数オブジェクトを作成します
(関数テンプレート) [edit]