Namespaces
Variants

std:: bind

From cppreference.net
Utilities library
Function objects
Function invocation
(C++17) (C++23)
Identity function object
(C++20)
Old binders and adaptors
( until C++17* )
( until C++17* )
( until C++17* )
( until C++17* )
( until C++17* ) ( until C++17* ) ( until C++17* ) ( until C++17* )
( until C++20* )
( until C++20* )
( until C++17* ) ( until C++17* )
( until C++17* ) ( until C++17* )

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

関数テンプレート std::bind f の転送呼び出しラッパーを生成します。このラッパーを呼び出すことは、 f をその引数の一部が バインドされた 状態で呼び出すことと等価です。

std:: is_constructible < std:: decay < F > :: type , F > :: value false である場合、または std:: is_constructible < std:: decay < Arg_i > :: type , Arg_i > :: value false である場合( Args 内の任意の型 Arg_i について)、プログラムは不適格(ill-formed)です。

std:: decay < Ti > :: type または Args 内のいずれかの型が MoveConstructible または Destructible でない場合、動作は未定義です。

目次

パラメータ

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

戻り値

未指定の型 T の関数オブジェクト g 。これに対して std:: is_bind_expression < T > :: value true となる。以下のメンバを持つ:

std::bind 戻り値型

メンバーオブジェクト

std::bind の戻り値型は、 std:: decay < F > :: type 型のメンバオブジェクトを保持します。これは std:: forward < F > ( f ) から構築されます。また、 args... の各引数に対して1つずつ、 std:: decay < Arg_i > :: type 型のオブジェクトを保持します。これらは同様に std:: forward < Arg_i > ( arg_i ) から構築されます。

コンストラクタ

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

メンバ型 result_type

1) (C++17で非推奨) F が関数ポインタまたはメンバ関数ポインタの場合、 result_type F の戻り値の型。 F がネストされたtypedef result_type を持つクラス型の場合、 result_type F::result_type となる。それ以外の場合、 result_type は定義されない。
2) (C++17で非推奨) result_type は正確に R である。
(C++20まで)

メンバー関数 operator()

g が関数呼び出し式 g ( u1, u2, ... uM ) で呼び出されるとき、格納されたオブジェクトの呼び出しが行われます。あたかも以下のように

1) INVOKE ( fd, std:: forward < V1 > ( v1 ) , std:: forward < V2 > ( v2 ) , ..., std:: forward < VN > ( vN ) ) 、または
2) INVOKE<R> ( fd, std:: forward < V1 > ( v1 ) , std:: forward < V2 > ( v2 ) , ..., std:: forward < VN > ( vN ) )

ここで fd は型 std:: decay < F > :: type の値であり、バインドされた引数 v1 , v2 , ..., vN の値と型は 後述 のように決定されます。

g ( ) の呼び出し時に指定された引数の一部が、 g に保存されたプレースホルダーと一致しない場合、未使用の引数は評価された後に破棄されます。

operator ( ) の呼び出しは、基となる INVOKE 操作がそうである場合に限り、 例外を送出しない か、 定数部分式 である (C++20以降) operator ( ) は、 INVOKE 操作が未評価オペランドとして扱われた場合に適切な形式である場合にのみ、オーバーロード解決に参加する。

g volatile 修飾されている場合、プログラムは不適格です。

もし INVOKE ( fd, w1, w2, ..., wN ) が、いかなる可能な値 w1 , w2 , ..., wN に対しても有効な式になり得ない場合、動作は未定義です。

バインド引数

格納された各引数 arg_i について、 INVOKE または INVOKE<R> 操作における対応する束縛引数 v_i は以下のように決定されます:

ケース1: リファレンスラッパー

arg_i が型 std:: reference_wrapper < T > の場合(例えば、 std::ref または std::cref std::bind の初期呼び出しで使用された場合)、 v_i arg_i. get ( ) となり、その型 V_i T& となります:保存された引数は参照によって呼び出される関数オブジェクトに渡されます。

Case 2: バインド式

arg_i の型が T であり、かつ std:: is_bind_expression < T > :: value true である場合(例えば、別の std::bind 式が初期の std::bind 呼び出しに直接渡された場合)、 std::bind は関数合成を実行します:バインド部分式が返す関数オブジェクトを渡す代わりに、部分式が積極的に呼び出され、その戻り値が外側の呼び出し可能オブジェクトに渡されます。バインド部分式がプレースホルダー引数を持つ場合、それらは外側のバインドと共有されます( u1 , u2 , ... から選択されます)。具体的には、 v_i arg_i ( std:: forward < Uj > ( uj ) ... ) であり、その型 V_i std:: result_of < T cv  & ( Uj && ... ) > :: type && (C++17まで) std:: invoke_result_t < T cv  & , Uj && ... > && (C++17以降) となります(cv修飾は g と同じです)。

Case 3: プレースホルダー

arg_i の型が T であり、かつ std:: is_placeholder < T > :: value 0 ではない場合(つまり、 std::placeholders::_1, _2, _3, ... のようなプレースホルダが std::bind の初期呼び出し時の引数として使用された場合)、そのプレースホルダが示す引数( _1 に対しては u1 _2 に対しては u2 、など)が呼び出し可能オブジェクトに渡されます: v_i std:: forward < Uj > ( uj ) であり、その型 V_i Uj&& となります。

Case 4: 通常の引数

それ以外の場合、 arg_i は左辺値引数として呼び出し可能オブジェクトに渡されます: v_i は単に arg_i であり、その型 V_i T cv  & となります。ここで cv g と同じcv修飾です。

例外

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

注記

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

bindへの引数はコピーまたはムーブされ、参照で渡されることはありません。ただし、 std::ref または std::cref でラップされた場合を除きます。

同じbind式内での重複プレースホルダー(例えば複数の _1 使用)は許可されますが、対応する引数( u1 )が左値または非移動可能な右値である場合にのみ結果が明確に定義されます。

#include <functional>
#include <iostream>
#include <memory>
#include <random>
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... 用
    std::cout << "1) 引数の順序変更と参照渡し: ";
    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) への呼び出しを行います
    std::cout << "2) 同じ効果をラムダを使用して達成する方法: ";
    n = 7;
    auto lambda = [&ncref = n, n](auto a, auto b, auto /*未使用*/)
    {
        f(b, 42, a, ncref, n);
    };
    n = 10;
    lambda(1, 2, 1001); // f1(1, 2, 1001) の呼び出しと同じ
    std::cout << "3) ネストされた 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::cout << "4) RNGを分布にバインドする: ";
    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';
    std::cout << "5) メンバ関数へのポインタにバインド: ";
    Foo foo;
    auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1);
    f3(5);
    std::cout << "6) メンバ関数へのポインタである mem_fn にバインドする: ";
    auto ptr_to_print_sum = std::mem_fn(&Foo::print_sum);
    auto f4 = std::bind(ptr_to_print_sum, &foo, 95, _1);
    f4(5);
    std::cout << "7) データメンバへのポインタへのバインド: ";
    auto f5 = std::bind(&Foo::data, _1);
    std::cout << f5(foo) << '\n';
    std::cout << "8) データメンバへのポインタである mem_fn にバインドする: ";
    auto ptr_to_data = std::mem_fn(&Foo::data);
    auto f6 = std::bind(ptr_to_data, _1);
    std::cout << f6(foo) << '\n';
    std::cout << "9) 参照されるオブジェクトのメンバーを呼び出すにはスマートポインタを使用する: ";
    std::cout << f6(std::make_shared<Foo>(foo)) << ' '
              << f6(std::make_unique<Foo>(foo)) << '\n';
}

出力:

1) 引数の順序変更と参照渡し: 2 42 1 10 7
2) ラムダを使用して同じ効果を達成: 2 42 1 10 7
3) ネストされたbind部分式はプレースホルダを共有: 12 12 12 4 5
4) 分布を持つRNGをバインド: 0 1 8 5 5 2 0 7 7 10 
5) メンバ関数へのポインタへのバインド: 100
6) メンバ関数へのポインタであるmem_fnへのバインド: 100
7) データメンバへのポインタへのバインド: 10
8) データメンバへのポインタであるmem_fnへのバインド: 10
9) スマートポインタを使用して参照先オブジェクトのメンバを呼び出し: 10 10

不具合報告

以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。

DR 適用対象 公開時の動作 正しい動作
LWG 2021 C++11 1. 束縛された引数が
fd に転送されなかった
2. ケース2において、 V_i の型が
std:: result_of < T cv  ( Uj... ) > :: type
1. 転送される
2. 以下に変更
std:: result_of < T cv  & ( Uj && ... ) > :: type &&

関連項目

(C++20) (C++23)
可変個の引数を順に関数オブジェクトにバインドする
(関数テンプレート)
std::bind 式内の未バインド引数のためのプレースホルダ
(定数)
(C++11)
メンバへのポインタから関数オブジェクトを作成する
(関数テンプレート)