最終更新日時: 2024年06月11日 22時45分38秒 (JST)
Akira Takahashi が更新

履歴 編集

function template
<functional>

# std::bind(C++11)

    namespace std {
      template <class F, class... BoundArgs>
      unspecified bind(F&& f, BoundArgs&&... bound_args);           // (1) C++11

      template <class F, class... BoundArgs>
      constexpr unspecified bind(F&& f, BoundArgs&&... bound_args); // (1) C++20

      template <class R, class F, class... BoundArgs>
      unspecified bind(F&& f, BoundArgs&&... bound_args);           // (2) C++11

      template <class R, class F, class... BoundArgs>
      constexpr unspecified bind(F&& f, BoundArgs&&... bound_args); // (2) C++20
    }

## 概要

Callable オブジェクトに対し、引数を部分的に束縛(bind)する。

## 引数

- `f` -- 束縛先となる Callable オブジェクト
- `bound_args` -- 束縛対象の値やプレースホルダ(`_1`, `_2`, ...)、別の `bind()` 呼び出し

## 戻り値

引数を部分束縛された Callable オブジェクト。このオブジェクトは、次のような関数オブジェクトとして扱うことができる：

    struct bound_function_type {
      using result_type = unspecified;
      template <class... UnBoundArgs>
      unspecified operator ()(UnBoundArgs&&... unbound_args) const;
    };

型名 `result_type` は、`bind()` 呼び出し時のテンプレートパラメータ `R` そのもの(明示的に指定した場合)か、`F` の戻り値型(`F` が関数へのポインタまたはメンバ関数へのポインタである場合)か、`F::result_type` (`F` が型名 `result_type` の定義を持つ場合)である。いずれの条件も満たさない場合、`result_type` は定義されない。

`bound_function_type``::operator ()()`を呼び出すと、`bound_args` と `unbound_args` が次のように使われ、最終的に `f` の呼出しに到達する。(説明用に、 `BoundArgs` のそれぞれの `decay` された型を `TiD` 、値を `ti` 、`UnBoundArgs` のそれぞれの値を `uj` とおく)。

1. 型`Ti` が `std::reference_wrapper<X>` である場合、`ti.get()` が `ti` の代わりに使用される。
2. `std::is_bind_expression<TiD>::value`が `true` に評価される場合、`ti(unbound_args...)` の結果が `ti` の代わりに使用される(これは、ネストされた `bind()` が一度の呼び出しで再帰的に全て評価されることを示す)。
3. `std::is_placeholder<TiD>::value`が非ゼロに評価される場合、`uj` (ただし `j = std::is_placeholder<Ti>::value+1`) が `ti` の代わりに使用される。
4. その他の場合、`ti` がそのまま使用される。 上記の置換を行った後、 `f(ti...)` を呼び出した結果が `bound_function_type``::operator ()()` の呼出し結果として返される。

注意： `bound_args` は明示的に `std::ref()` または `std::cref()` で包まない限り、内部でコピーして保持される。他方、`unbound_args` は通常の perfect forwarding が行われるため、`move` で渡したあるいは一時オブジェクトを直接渡した `unbound_args` を複数回プレースホルダ経由で使用すると予期しない結果になることがある。

## 例外

戻り値のオブジェクト内に束縛する、関数オブジェクト`f`およびその引数`boud_args`の初期化時に例外を投げる可能性がある。

## 例

    #include <iostream>
    #include <functional>

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

    class Foo {
    public:
      int n;
      Foo(int n) : n(n) {}
      Foo add(int n2) const
      {
        return this->n + n2;
      }
    };

    int main()
    {
      // 第1引数のみを先に渡す
      using namespace std::placeholders;
      std::function<int(int, int)> f1 = std::bind(add, 2, _1, _2);

      // 残りの引数を渡して関数を呼び出す
      const int result1 = f1(3, 4);

      Foo foo{2};

      // thisにするもののみを先に渡す
      std::function<Foo(int)> f2 = std::bind(&Foo::add, foo, _1);

      // 残りの引数を渡して関数を呼び出す
      const auto result2 = f2(3);

      std::cout << result1 << ',' << result2.n << std::endl;
    }

### 出力

    9,5

## バージョン

### 言語

- C++11

### 処理系

- Clang: ??
- GCC: 4.7.0 ✅
- ICC: ??
- Visual C++: ??

## 参照

- LWG Issue 2021. Further incorrect usages of `result_of`
- P1065R2 constexpr INVOKE