Namespaces
Variants

std:: bind_front, std:: bind_back

From cppreference.net
< cpp β€Ž | utility β€Ž | functional
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 λŠ” 호좜 κ°€λŠ₯ λŒ€μƒ(callable target)을 (1,2) 첫 번째 λ˜λŠ” (3,4) λ§ˆμ§€λ§‰ sizeof... ( Args ) 개의 λ§€κ°œλ³€μˆ˜λ₯Ό args 에 λ°”μΈλ”©ν•˜μ—¬ μ™„λ²½ν•œ 전달(perfect forwarding) 호좜 래퍼λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.

1,3) 호좜 λž˜νΌλŠ” λŒ€μƒ 호좜 κ°€λŠ₯ 객체 f 의 볡사본을 λ³΄μœ ν•©λ‹ˆλ‹€.
2,4) 호좜 λž˜νΌλŠ” 호좜 κ°€λŠ₯ λŒ€μƒμ„ λ³΄μœ ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€(μ •μ μœΌλ‘œ 결정됨).
1) std :: bind_front ( f, bound_args... ) ( call_args... ) λŠ” ν‘œν˜„μ‹ 동등 ν•©λ‹ˆλ‹€
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... ) λŠ” ν‘œν˜„μ‹ 동등 ν•©λ‹ˆλ‹€
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 λ₯Ό 두 번 ν˜ΈμΆœν•˜μ—¬ λ°˜ν™˜λœ κ°μ²΄λ“€μ˜ νƒ€μž…μ΄ λ™μΌν•˜λ‹€λŠ” 점만 μ˜ˆμ™Έμž…λ‹ˆλ‹€.

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()

이전 ν˜ΈμΆœμ—μ„œ 얻은 객체 G κ°€ ( 1,3 ) bind-partial (f, args...) λ˜λŠ” ( 2,4 ) bind-partial <ConstFn>(args...) λ‘œλΆ€ν„° μ–»μ–΄μ‘Œμ„ λ•Œ, glvalue g κ°€ 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 일 λ•Œ

μ—¬κΈ°μ„œ

  • Ns λŠ” μ •μˆ˜ 팩 0, 1, ..., (sizeof...(Args) - 1) μž…λ‹ˆλ‹€,
  • g λŠ” 호좜 ν‘œν˜„μ‹μ—μ„œ lvalue인 경우 std::invoke ν‘œν˜„μ‹μ—μ„œ lvalue이며, κ·Έλ ‡μ§€ μ•Šμ€ 경우 rvalueμž…λ‹ˆλ‹€. λ”°λΌμ„œ std :: move ( g ) ( call_args... ) λŠ” λ°”μΈλ”©λœ μΈμžλ“€μ„ 호좜둜 μ΄λ™μ‹œν‚¬ 수 μžˆμ§€λ§Œ, g ( call_args... ) λŠ” λ³΅μ‚¬ν•©λ‹ˆλ‹€.

ν”„λ‘œκ·Έλž¨μ€ g κ°€ volatile ν•œμ • νƒ€μž…μ„ κ°€μ§ˆ 경우 ν˜•μ‹μ΄ 잘λͺ»λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

멀버 operator ( ) λŠ” noexcept μž…λ‹ˆλ‹€. λ§Œμ•½ std::invoke ν‘œν˜„μ‹μ΄ noexcept인 경우 (λ‹€μ‹œ 말해, κΈ°λ³Έ 호좜 μ—°μ‚°μžμ˜ μ˜ˆμ™Έ λͺ…μ„Έλ₯Ό λ³΄μ‘΄ν•©λ‹ˆλ‹€).

μ˜ˆμ™Έ

1,3) μ €μž₯된 ν•¨μˆ˜ 객체의 μƒμ„±μžλ₯Ό ν˜ΈμΆœν•˜μ—¬ λ°œμƒν•˜λŠ” λͺ¨λ“  μ˜ˆμ™Έλ₯Ό throwν•©λ‹ˆλ‹€.
1-4) λ°”μΈλ”©λœ 인수 쀑 μ–΄λ–€ κ²ƒμ˜ μƒμ„±μžλ₯Ό ν˜ΈμΆœν•  λ•Œ λ°œμƒν•˜λŠ” λͺ¨λ“  μ˜ˆμ™Έλ₯Ό λ˜μ§‘λ‹ˆλ‹€.

μ°Έκ³  사항

이 ν•¨μˆ˜ ν…œν”Œλ¦Ώλ“€μ€ std::bind λ₯Ό λŒ€μ²΄ν•˜κΈ° μœ„ν•΄ κ³ μ•ˆλ˜μ—ˆμŠ΅λ‹ˆλ‹€. std::bind 와 달리, 이듀은 μž„μ˜μ˜ 인자 μž¬λ°°μ—΄μ„ μ§€μ›ν•˜μ§€ μ•ŠμœΌλ©° μ€‘μ²©λœ bind-expressionμ΄λ‚˜ std::reference_wrapper 에 λŒ€ν•œ νŠΉλ³„ν•œ 처리λ₯Ό μ œκ³΅ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. λ°˜λ©΄μ—, 이듀은 호좜 래퍼 객체의 κ°’ λ²”μ£Ό(value category)λ₯Ό κ³ λ €ν•˜λ©° κΈ°λ³Έ 호좜 μ—°μ‚°μžμ˜ μ˜ˆμ™Έ λͺ…μ„Έ(exception specification)λ₯Ό μ „νŒŒν•©λ‹ˆλ‹€.

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) 호좜 κ°€λŠ₯ 객체λ₯Ό μƒμˆ˜ ν…œν”Œλ¦Ώ 인수둜 std::bind_front 에 전달 ν—ˆμš©, ( 2 )
__cpp_lib_bind_back 202202L (C++23) std::bind_back , ( 3 )
202306L (C++26) 호좜 κ°€λŠ₯ 객체λ₯Ό μƒμˆ˜ ν…œν”Œλ¦Ώ 인수둜 std::bind_back 에 전달 ν—ˆμš©, ( 4 )

κ°€λŠ₯ν•œ κ΅¬ν˜„

(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)
ν•˜λ‚˜ μ΄μƒμ˜ 인수λ₯Ό ν•¨μˆ˜ 객체에 λ°”μΈλ”©ν•©λ‹ˆλ‹€
(function template)
(C++11)
멀버 ν¬μΈν„°λ‘œλΆ€ν„° ν•¨μˆ˜ 객체λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€
(function template)