Namespaces
Variants

std:: bind_front, std:: bind_back

From cppreference.net
Utilities library
Function objects
Partial function application
bind_front bind_back
(C++20) (C++23)
(C++11)
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>
std::bind_front
template < class F, class ... Args >
constexpr /* unspecified */ bind_front ( F && f, Args && ... args ) ;
(1) (C++20以降)
template < auto ConstFn, class ... Args >
constexpr /* unspecified */ bind_front ( Args && ... args ) ;
(2) (C++26以降)
std::bind_back
template < class F, class ... Args >
constexpr /* unspecified */ bind_back ( F && f, Args && ... args ) ;
(3) (C++23以降)
template < auto ConstFn, class ... Args >
constexpr /* unspecified */ bind_back ( Args && ... args ) ;
(4) (C++26以降)

関数テンプレート std::bind_front および std::bind_back は、呼び出し可能なターゲットをその (1,2) 最初の、または (3,4) 最後の sizeof... ( Args ) 個のパラメータを args に束縛して呼び出すことを可能にする完全転送呼び出しラッパーを生成します。

1,3) 呼び出しラッパーは対象の呼び出し可能オブジェクト f のコピーを保持します。
2,4) 呼び出しラッパーは呼び出し可能なターゲットを保持しません(静的に決定されます)。
1) std :: bind_front ( f, bound_args... ) ( call_args... ) expression-equivalent です
std:: invoke ( f, bound_args..., call_args... ) を実行します。
2) std :: bind_front < ConstFn > ( bound_args... ) ( call_args... ) 式等価 です
std:: invoke ( ConstFn, bound_args..., call_args... ) .
3) std :: bind_back ( f, bound_args... ) ( call_args... ) expression-equivalent です
std:: invoke ( f, call_args..., bound_args... ) を呼び出します。
4) std :: bind_back < ConstFn > ( bound_args... ) ( call_args... ) 式等価 です
std:: invoke ( ConstFn, call_args..., bound_args... ) .

以下の条件が true でなければなりません。そうでない場合、プログラムは不適格となります:

目次

パラメータ

f - Callable オブジェクト(関数オブジェクト、関数へのポインタ、関数への参照、メンバ関数へのポインタ、またはデータメンバへのポインタ)で、いくつかの引数に束縛されるもの
args - 呼び出し可能ターゲットの ( 1,2 ) 最初または ( 3,4 ) 最後の sizeof... ( Args ) 個のパラメータに束縛する引数のリスト
型要件
-
std:: decay_t < F > MoveConstructible の要件を満たさなければならない
-
std:: decay_t < Args > ... MoveConstructible の要件を満たさなければならない
-
decltype ( ConstFn ) Callable の要件を満たさなければならない

戻り値

関数オブジェクト(呼び出しラッパー)の型は T で、その詳細は規定されていない。ただし、同じ引数で std::bind_front または std::bind_back を2回呼び出した場合に返されるオブジェクトの型は同じである。

bind-partial std::bind_front または std::bind_back のいずれかとします。

返されたオブジェクトは以下のプロパティを持ちます:

bind-partial 戻り値型

メンバーオブジェクト

返されるオブジェクトは、以下のように保持しているかのように振る舞います:

1,3) メンバーオブジェクト fd は型 std:: decay_t < F > で、 std:: forward < F > ( f ) からの直接非リスト初期化により初期化され、かつ
1-4) std::tuple オブジェクト tup std:: tuple < std:: decay_t < Args > ... > ( std:: forward < Args > ( args ) ... ) で構築されるが、返されるオブジェクトの代入動作は未規定であり、名前は説明専用である。

コンストラクタ

bind-partial の戻り値の型は、そのコピー/ムーブコンストラクタがメンバーごとのコピー/ムーブを実行するかのように振る舞います。これは、 CopyConstructible すべてのメンバーオブジェクト(上記で指定)が CopyConstructible である場合に MoveConstructible であり、それ以外の場合は です。

メンバー関数 operator()

以前の呼び出し ( 1,3 ) bind-partial (f, args...) または ( 2,4 ) bind-partial <ConstFn>(args...) から取得したオブジェクト G が与えられたとき、 G を指すglvalue g が関数呼び出し式 g ( call_args... ) で呼び出されると、保存されたオブジェクトの呼び出しが以下のように行われます:

1) std:: invoke ( g. fd , std :: get < Ns > ( g. tup ) ..., call_args... ) bind-partial std::bind_front の場合、
2) std:: invoke ( ConstFn, std :: get < Ns > ( g. tup ) ..., call_args... ) bind-partial std::bind_front の場合、
3) std:: invoke ( g. fd , call_args..., std :: get < Ns > ( g. tup ) ... ) bind-partial std::bind_back である場合、
4) std:: invoke ( ConstFn, call_args..., std :: get < Ns > ( g. tup ) ... ) bind-partial std::bind_back の場合、

where

  • Ns は整数パック 0, 1, ..., (sizeof...(Args) - 1) です。
  • g は、呼び出し式で左辺値の場合 std::invoke 式では左辺値となり、それ以外の場合は右辺値となります。したがって、 std :: move ( g ) ( call_args... ) は束縛された引数を呼び出しに移動できますが、 g ( call_args... ) はコピーします。

プログラムは、 g がvolatile修飾型を持つ場合、不適格です。

メンバー関数 operator ( ) は、 noexcept が呼び出す std::invoke 式がnoexceptである場合にnoexceptとなります(言い換えれば、基盤となる呼び出し演算子の例外仕様を保持します)。

例外

1,3) 格納された関数オブジェクトのコンストラクタ呼び出しによって送出されるあらゆる例外を送出します。
1-4) バインドされた引数のいずれかのコンストラクタ呼び出しによってスローされた例外をスローします。

注記

これらの関数テンプレートは std::bind を置き換えることを目的としています。 std::bind とは異なり、任意の引数の再配置をサポートせず、ネストされたbind式や std::reference_wrapper に対する特別な扱いもありません。一方で、呼び出しラッパーオブジェクトの値カテゴリに注意を払い、基底となる呼び出し演算子の例外指定を伝播します。

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

std::bind_front または std::bind_back への引数は、コピーまたはムーブされ、 std::ref または std::cref でラップされない限り、参照渡しされることはありません。

通常、関数またはメンバ関数への引数のバインディングには ( 1 ) std::bind_front および ( 3 ) std::bind_back を使用しますが、これには言語がポインタをデリファレンスする必要なく呼び出すべき関数を正確に知っているにもかかわらず、関数ポインタと引数を保存する必要があります。このような場合に「ゼロコスト」を保証するため、C++26では ( 2,4 ) バージョン(呼び出し可能オブジェクトを 定数テンプレートパラメータ の引数として受け入れる)が導入されました。

機能テスト マクロ 標準 機能
__cpp_lib_bind_front 201907L (C++20) std::bind_front , ( 1 )
202306L (C++26) callableオブジェクトを定数テンプレート引数として std::bind_front に渡すことを許可, ( 2 )
__cpp_lib_bind_back 202202L (C++23) std::bind_back , ( 3 )
202306L (C++26) callableオブジェクトを定数テンプレート引数として std::bind_back に渡すことを許可, ( 4 )

実装例

**注記**: このC++コードは技術的な内容を含むため、HTMLタグ、属性、および` `、`
`、``タグ内のテキストは翻訳せず、C++固有の用語もそのまま保持しています。コードの構造とフォーマットは完全に維持されています。
(2) bind_front
namespace detail
{
    template<class T, class U>
    struct copy_const
        : std::conditional<std::is_const_v<T>, U const, U> {};
    template<class T, class U,
             class X = typename copy_const<std::remove_reference_t<T>, U>::type>
    struct copy_value_category
        : std::conditional<std::is_lvalue_reference_v<T&&>, X&, X&&> {};
    template <class T, class U>
    struct type_forward_like
        : copy_value_category<T, std::remove_reference_t<U>> {};
    template <class T, class U>
    using type_forward_like_t = typename type_forward_like<T, U>::type;
}
template<auto ConstFn, class... Args>
constexpr auto bind_front(Args&&... args)
{
    using F = decltype(ConstFn);
    if constexpr (std::is_pointer_v<F> or std::is_member_pointer_v<F>)
        static_assert(ConstFn != nullptr);
    return
        [... bound_args(std::forward<Args>(args))]<class Self, class... T>
        (
            this Self&&, T&&... call_args
        )
        noexcept
        (
            std::is_nothrow_invocable_v<F,
                detail::type_forward_like_t<Self, std::decay_t<Args>>..., T...>
        )
        -> std::invoke_result_t<F,
                detail::type_forward_like_t<Self, std::decay_t<Args>>..., T...>
        {
            return std::invoke(ConstFn, std::forward_like<Self>(bound_args)...,
                               std::forward<T>(call_args)...);
        };
}
(4) bind_back
namespace detail { /* 上記と同じ */ }
template<auto ConstFn, class... Args>
constexpr auto bind_back(Args&&... args)
{
    using F = decltype(ConstFn);
    if constexpr (std::is_pointer_v<F> or std::is_member_pointer_v<F>)
        static_assert(ConstFn != nullptr);
    return
        [... bound_args(std::forward<Args>(args))]<class Self, class... T>
        (
            this Self&&, T&&... call_args
        )
        noexcept
        (
            std::is_nothrow_invocable_v<F,
                detail::type_forward_like_t<Self, T..., std::decay_t<Args>>...>
        )
        -> std::invoke_result_t<F,
                detail::type_forward_like_t<Self, T..., std::decay_t<Args>>...>
        {
            return std::invoke(ConstFn, std::forward<T>(call_args)...,
                               std::forward_like<Self>(bound_args)...);
        };
}

#include <cassert>
#include <functional>
int minus(int a, int b)
{
    return a - b;
}
struct S
{
    int val;
    int minus(int arg) const noexcept { return val - arg; }
};
int main()
{
    auto fifty_minus = std::bind_front(minus, 50);
    assert(fifty_minus(3) == 47); // 次と等価: minus(50, 3) == 47
    auto member_minus = std::bind_front(&S::minus, S{50});
    assert(member_minus(3) == 47); //: S tmp{50}; tmp.minus(3) == 47
    // noexcept指定は保持される:
    static_assert(!noexcept(fifty_minus(3)));
    static_assert(noexcept(member_minus(3)));
    // ラムダのバインド:
    auto plus = [](int a, int b) { return a + b; };
    auto forty_plus = std::bind_front(plus, 40);
    assert(forty_plus(7) == 47); // 次と等価: plus(40, 7) == 47
#if __cpp_lib_bind_front >= 202306L
    auto fifty_minus_cpp26 = std::bind_front<minus>(50);
    assert(fifty_minus_cpp26(3) == 47);
    auto member_minus_cpp26 = std::bind_front<&S::minus>(S{50});
    assert(member_minus_cpp26(3) == 47);
    auto forty_plus_cpp26 = std::bind_front<plus>(40);
    assert(forty_plus(7) == 47);
#endif
#if __cpp_lib_bind_back >= 202202L
    auto madd = [](int a, int b, int c) { return a * b + c; };
    auto mul_plus_seven = std::bind_back(madd, 7);
    assert(mul_plus_seven(4, 10) == 47); //: madd(4, 10, 7) == 47
#endif
#if __cpp_lib_bind_back >= 202306L
    auto mul_plus_seven_cpp26 = std::bind_back<madd>(7);
    assert(mul_plus_seven_cpp26(4, 10) == 47);
#endif
}

参考文献

  • C++26標準 (ISO/IEC 14882:2026):
  • TBD 関数テンプレート bind_front および bind_back [func.bind.partial]
  • C++23標準 (ISO/IEC 14882:2024):
  • 22.10.14 関数テンプレート bind_front および bind_back [func.bind.partial]
  • C++20規格 (ISO/IEC 14882:2020):
  • 20.14.14 関数テンプレート bind_front [func.bind.front]

関連項目

(C++11)
1つ以上の引数を関数オブジェクトにバインドする
(関数テンプレート)
(C++11)
メンバへのポインタから関数オブジェクトを作成する
(関数テンプレート)