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* )
Definido en el encabezado <functional>
std::bind_front
template < class F, class ... Args >
constexpr /* no especificado */ bind_front ( F && f, Args && ... args ) ;
(1) (desde C++20)
template < auto ConstFn, class ... Args >
constexpr /* no especificado */ bind_front ( Args && ... args ) ;
(2) (desde C++26)
std::bind_back
template < class F, class ... Args >
constexpr /* no especificado */ bind_back ( F && f, Args && ... args ) ;
(3) (desde C++23)
template < auto ConstFn, class ... Args >
constexpr /* no especificado */ bind_back ( Args && ... args ) ;
(4) (desde C++26)

Las plantillas de función std::bind_front y std::bind_back generan un envoltorio de llamada de reenvío perfecto que permite invocar el objetivo invocable con sus (1,2) primeros o (3,4) últimos sizeof... ( Args ) parámetros vinculados a args .

1,3) El contenedor de llamadas mantiene una copia del objeto invocable objetivo f .
2,4) El envoltorio de llamada no contiene un destino invocable (se determina estáticamente).
1) std :: bind_front ( f, bound_args... ) ( call_args... ) es equivalente-expresión a
std:: invoke ( f, bound_args..., call_args... ) .
2) std :: bind_front < ConstFn > ( bound_args... ) ( call_args... ) es equivalente-expresión a
std:: invoke ( ConstFn, bound_args..., call_args... ) .
3) std :: bind_back ( f, bound_args... ) ( call_args... ) es equivalente-expresión a
std:: invoke ( f, call_args..., bound_args... ) .
4) std :: bind_back < ConstFn > ( bound_args... ) ( call_args... ) es equivalente-expresión a
std:: invoke ( ConstFn, call_args..., bound_args... ) .

Las siguientes condiciones deben ser true , de lo contrario el programa está mal formado:

Contenidos

Parámetros

f - Callable objeto (objeto función, puntero a función, referencia a función, puntero a función miembro, o puntero a miembro de datos) que será vinculado a algunos argumentos
args - lista de los argumentos a vincular a los ( 1,2 ) primeros o ( 3,4 ) últimos sizeof... ( Args ) parámetros del objetivo invocable
Requisitos de tipo
-
std:: decay_t < F > debe cumplir con los requisitos de MoveConstructible .
-
std:: decay_t < Args > ... debe cumplir con los requisitos de MoveConstructible .
-
decltype ( ConstFn ) debe cumplir con los requisitos de Callable .

Valor de retorno

Un objeto función (el envoltorio de llamada) de tipo T que no está especificado, excepto que los tipos de objetos devueltos por dos llamadas a std::bind_front o std::bind_back con los mismos argumentos son los mismos.

Sea bind-partial ya sea std::bind_front o std::bind_back .

El objeto devuelto tiene las siguientes propiedades:

bind-partial tipo de retorno

Objetos miembro

El objeto devuelto se comporta como si contuviera:

1,3) Un objeto miembro fd de tipo std:: decay_t < F > inicializado por non-lista directa desde std:: forward < F > ( f ) , y
1-4) Un objeto std::tuple tup construido con std:: tuple < std:: decay_t < Args > ... > ( std:: forward < Args > ( args ) ... ) , excepto que el comportamiento de asignación del objeto devuelto no está especificado y los nombres son solo para exposición.

Constructores

El tipo de retorno de bind-partial se comporta como si sus constructores de copia/movimiento realizaran una copia/movimiento miembro a miembro. Es CopyConstructible si todos sus objetos miembro (especificados anteriormente) son CopyConstructible , y es MoveConstructible en caso contrario.

Función miembro operator()

Dado un objeto G obtenido de una llamada anterior a ( 1,3 ) bind-partial (f, args...) o ( 2,4 ) bind-partial <ConstFn>(args...) , cuando un glvalue g que designa G es invocado en una expresión de llamada a función g ( call_args... ) , tiene lugar una invocación del objeto almacenado, como si fuera mediante:

1) std:: invoke ( g. fd , std :: get < Ns > ( g. tup ) ..., call_args... ) , cuando bind-partial es std::bind_front ,
2) std:: invoke ( ConstFn, std :: get < Ns > ( g. tup ) ..., call_args... ) , cuando bind-partial es std::bind_front ,
3) std:: invoke ( g. fd , call_args..., std :: get < Ns > ( g. tup ) ... ) , cuando bind-partial es std::bind_back ,
4) std:: invoke ( ConstFn, call_args..., std :: get < Ns > ( g. tup ) ... ) , cuando bind-partial es std::bind_back ,

donde

  • Ns es un paquete de enteros 0, 1, ..., (sizeof...(Args) - 1) ,
  • g es un lvalue en la expresión std::invoke si es un lvalue en la expresión de llamada, y es un rvalue en caso contrario. Por lo tanto std :: move ( g ) ( call_args... ) puede mover los argumentos vinculados a la llamada, mientras que g ( call_args... ) copiaría.

El programa está mal formado si g tiene tipo calificado como volatile.

El miembro operator ( ) es noexcept si la expresión std::invoke que llama es noexcept (en otras palabras, preserva la especificación de excepciones del operador de llamada subyacente).

Excepciones

1,3) Lanza cualquier excepción lanzada al llamar al constructor del objeto de función almacenado.
1-4) Lance cualquier excepción lanzada al llamar al constructor de cualquiera de los argumentos vinculados.

Notas

Estas plantillas de función están destinadas a reemplazar std::bind . A diferencia de std::bind , no admiten reordenamiento arbitrario de argumentos y no tienen tratamiento especial para expresiones de enlace anidadas o std::reference_wrapper s. Por otro lado, prestan atención a la categoría de valor del objeto contenedor de llamada y propagan la especificación de excepciones del operador de llamada subyacente.

Como se describe en std::invoke , al invocar un puntero a función miembro no estática o puntero a dato miembro no estático, el primer argumento debe ser una referencia o puntero (incluyendo, posiblemente, punteros inteligentes como std::shared_ptr y std::unique_ptr ) a un objeto cuyo miembro será accedido.

Los argumentos de std::bind_front o std::bind_back se copian o mueven, y nunca se pasan por referencia a menos que se envuelvan en std::ref o std::cref .

Normalmente, enlazar argumentos a una función o a una función miembro usando ( 1 ) std::bind_front y ( 3 ) std::bind_back requiere almacenar un puntero a función junto con los argumentos, aunque el lenguaje sabe exactamente qué función llamar sin necesidad de desreferenciar el puntero. Para garantizar "costo cero" en esos casos, C++26 introduce las versiones ( 2,4 ) (que aceptan el objeto invocable como argumento para parámetro de plantilla constante ).

Macro de prueba de características Valor Std Característica
__cpp_lib_bind_front 201907L (C++20) std::bind_front , ( 1 )
202306L (C++26) Permitir pasar objetos invocables como argumentos de plantilla constantes a std::bind_front , ( 2 )
__cpp_lib_bind_back 202202L (C++23) std::bind_back , ( 3 )
202306L (C++26) Permitir pasar objetos invocables como argumentos de plantilla constantes a std::bind_back , ( 4 )

Implementación posible

(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 { /* es lo mismo que arriba */ }
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)...);
        };
}

Ejemplo

#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); // equivalente a: 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
    // La especificación noexcept se conserva:
    static_assert(!noexcept(fifty_minus(3)));
    static_assert(noexcept(member_minus(3)));
    // Enlace de una lambda:
    auto plus = [](int a, int b) { return a + b; };
    auto forty_plus = std::bind_front(plus, 40);
    assert(forty_plus(7) == 47); // equivalente a: 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
}

Referencias

  • Estándar C++26 (ISO/IEC 14882:2026):
  • TBD Plantillas de función bind_front y bind_back [func.bind.partial]
  • Estándar C++23 (ISO/IEC 14882:2024):
  • 22.10.14 Plantillas de función bind_front y bind_back [func.bind.partial]
  • Estándar C++20 (ISO/IEC 14882:2020):
  • 20.14.14 Plantilla de función bind_front [func.bind.front]

Véase también

(C++11)
vincula uno o más argumentos a un objeto función
(plantilla de función)
(C++11)
crea un objeto función a partir de un puntero a miembro
(plantilla de función)