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* )
Definido en el encabezado <functional>
template < class F, class ... Args >
/* unspecified */ bind ( F && f, Args && ... args ) ;
(1) (desde C++11)
(constexpr desde C++20)
template < class R, class F, class ... Args >
/* unspecified */ bind ( F && f, Args && ... args ) ;
(2) (desde C++11)
(constexpr desde C++20)

La plantilla de función std::bind genera un wrapper de llamada de reenvío para f . Llamar a este wrapper es equivalente a invocar f con algunos de sus argumentos vinculados a args .

Si std:: is_constructible < std:: decay < F > :: type , F > :: value es false , o std:: is_constructible < std:: decay < Arg_i > :: type , Arg_i > :: value es false para cualquier tipo Arg_i en Args , el programa está mal formado.

Si std:: decay < Ti > :: type o cualquier tipo en Args no es MoveConstructible o Destructible , el comportamiento es indefinido.

Contenidos

Parámetros

f - Callable objeto invocable (objeto función, puntero a función, referencia a función, puntero a función miembro, o puntero a dato miembro) que será vinculado a algunos argumentos
args - lista de argumentos a vincular, con los argumentos no vinculados reemplazados por los placeholders _1 , _2 , _3 ... del espacio de nombres std::placeholders

Valor de retorno

Un objeto función g de tipo no especificado T , para el cual std:: is_bind_expression < T > :: value es true . Tiene los siguientes miembros:

std::bind tipo de retorno

Objetos miembro

El tipo de retorno de std::bind contiene un objeto miembro de tipo std:: decay < F > :: type construido a partir de std:: forward < F > ( f ) , y un objeto por cada uno de args... , de tipo std:: decay < Arg_i > :: type , similarmente construido a partir de std:: forward < Arg_i > ( arg_i ) .

Constructores

El tipo de retorno de std::bind es CopyConstructible si todos sus objetos miembro (especificados anteriormente) son CopyConstructible, y es MoveConstructible en caso contrario. El tipo define los siguientes miembros:

Tipo miembro result_type

1) (obsoleto en C++17) Si F es un puntero a función o un puntero a función miembro, result_type es el tipo de retorno de F . Si F es un tipo clase con el typedef anidado result_type , entonces result_type es F::result_type . En caso contrario, no se define result_type .
2) (obsoleto en C++17) result_type es exactamente R .
(hasta C++20)

Función miembro operator()

Cuando g es invocado en una expresión de llamada a función g ( u1, u2, ... uM ) , tiene lugar una invocación del objeto almacenado, como si fuera mediante

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

donde fd es un valor de tipo std:: decay < F > :: type , los valores y tipos de los argumentos vinculados v1 , v2 , ..., vN se determinan como se especifica a continuación .

Si algunos de los argumentos que se suministran en la llamada a g ( ) no coinciden con ningún marcador de posición almacenado en g , los argumentos no utilizados se evalúan y descartan.

Una invocación de operator ( ) es no-lanzante o es una subexpresión constante (desde C++20) si y solo si lo es la operación subyacente INVOKE . operator ( ) participa en la resolución de sobrecarga solo si la operación INVOKE está bien formada cuando se trata como un operando no evaluado.

Si g está calificado como volatile , el programa está mal formado.

Si INVOKE ( fd, w1, w2, ..., wN ) nunca puede ser una expresión válida para cualquier valor posible w1 , w2 , ..., wN , el comportamiento no está definido.

Argumentos vinculados

Para cada argumento almacenado arg_i , el argumento vinculado correspondiente v_i en la operación INVOKE o INVOKE<R> se determina de la siguiente manera:

Caso 1: reference wrappers

Si arg_i es de tipo std:: reference_wrapper < T > (por ejemplo, std::ref o std::cref se utilizó en la llamada inicial a std::bind ), entonces v_i es arg_i. get ( ) y su tipo V_i es T& : el argumento almacenado se pasa por referencia al objeto función invocado.

Caso 2: expresiones bind

Si arg_i es de tipo T para el cual std:: is_bind_expression < T > :: value es true (por ejemplo, otra expresión std::bind se pasó directamente a la llamada inicial de std::bind ), entonces std::bind realiza composición de funciones: en lugar de pasar el objeto función que devolvería la subexpresión bind, la subexpresión se invoca inmediatamente, y su valor de retorno se pasa al objeto invocable externo. Si la subexpresión bind tiene argumentos de marcador de posición, estos se comparten con el bind externo (seleccionados de u1 , u2 , ... ). Específicamente, v_i es arg_i ( std:: forward < Uj > ( uj ) ... ) y su tipo V_i es std:: result_of < T cv  & ( Uj && ... ) > :: type && (hasta C++17) std:: invoke_result_t < T cv  & , Uj && ... > && (desde C++17) (la calificación cv es la misma que la de g ).

Caso 3: placeholders

Si arg_i es de tipo T , para el cual std:: is_placeholder < T > :: value no es 0 (es decir, se utilizó un marcador de posición como std::placeholders::_1, _2, _3, ... como argumento en la llamada inicial a std::bind ), entonces el argumento indicado por el marcador de posición ( u1 para _1 , u2 para _2 , etc.) se pasa al objeto invocable: v_i es std:: forward < Uj > ( uj ) y su tipo V_i es Uj&& .

Caso 4: argumentos ordinarios

De lo contrario, arg_i se pasa al objeto invocable como argumento lvalue: v_i es simplemente arg_i y su tipo V_i es T cv  & , donde cv es la misma calificación cv que la de g .

Excepciones

Solo lanza si la construcción de std:: decay < F > :: type desde std:: forward < F > ( f ) lanza, o cualquiera de los constructores para std:: decay < Arg_i > :: type desde el correspondiente std:: forward < Arg_i > ( arg_i ) lanza donde Arg_i es el i-ésimo tipo y arg_i es el i-ésimo argumento en Args... args .

Notas

Como se describe en Callable , 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 para bind son copiados o movidos, y nunca se pasan por referencia a menos que se envuelvan en std::ref o std::cref .

Se permiten marcadores de posición duplicados en la misma expresión de enlace (múltiples _1 por ejemplo), pero los resultados solo están bien definidos si el argumento correspondiente ( u1 ) es un lvalue o un rvalue no movible.

Ejemplo

#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;  // para _1, _2, _3...
    std::cout << "1) reordenamiento de argumentos y paso por referencia: ";
    int n = 7;
    // (_1 y _2 son de std::placeholders, y representan futuros
    // argumentos que se pasarán a f1)
    auto f1 = std::bind(f, _2, 42, _1, std::cref(n), n);
    n = 10;
    f1(1, 2, 1001); // 1 está vinculado por _1, 2 está vinculado por _2, 1001 no se utiliza
                    // realiza una llamada a f(2, 42, 1, n, 7)
    std::cout << "2) lograr el mismo efecto usando una lambda: ";
    n = 7;
    auto lambda = [&ncref = n, n](auto a, auto b, auto /*sin usar*/)
    {
        f(b, 42, a, ncref, n);
    };
    n = 10;
    lambda(1, 2, 1001); // igual que una llamada a f1(1, 2, 1001)
    std::cout << "3) las expresiones de enlace anidadas comparten los marcadores de posición: ";
    auto f2 = std::bind(f, _3, std::bind(g, _3), _3, 4, 5);
    f2(10, 11, 12); // realiza una llamada a f(12, g(12), 12, 4, 5);
    std::cout << "4) vincular un RNG con una distribución: ";
    std::default_random_engine e;
    std::uniform_int_distribution<> d(0, 10);
    auto rnd = std::bind(d, e); // una copia de e se almacena en rnd
    for (int n = 0; n < 10; ++n)
        std::cout << rnd() << ' ';
    std::cout << '\n';
    std::cout << "5) enlazar a un puntero a función miembro: ";
    Foo foo;
    auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1);
    f3(5);
    std::cout << "6) vincular a un mem_fn que es un puntero a función miembro: ";
    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) bind a un puntero a miembro de datos: ";
    auto f5 = std::bind(&Foo::data, _1);
    std::cout << f5(foo) << '\n';
    std::cout << "8) enlazar a un mem_fn que es un puntero a miembro de datos: ";
    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) use smart pointers para llamar a miembros de los objetos referenciados: ";
    std::cout << f6(std::make_shared<Foo>(foo)) << ' '
              << f6(std::make_unique<Foo>(foo)) << '\n';
}

Salida:

1) reordenamiento de argumentos y paso por referencia: 2 42 1 10 7
2) lograr el mismo efecto usando una lambda: 2 42 1 10 7
3) las subexpresiones de bind anidadas comparten los placeholders: 12 12 12 4 5
4) vincular un RNG con una distribución: 0 1 8 5 5 2 0 7 7 10 
5) vincular a un puntero a función miembro: 100
6) vincular a un mem_fn que es un puntero a función miembro: 100
7) vincular a un puntero a miembro de datos: 10
8) vincular a un mem_fn que es un puntero a miembro de datos: 10
9) usar punteros inteligentes para llamar a miembros de los objetos referenciados: 10 10

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
LWG 2021 C++11 1. los argumentos ligados
no se reenviaban a fd
2. en el caso 2, el tipo de V_i era
std:: result_of < T cv  ( Uj... ) > :: type
1. reenviados
2. cambiado a
std:: result_of < T cv  & ( Uj && ... ) > :: type &&

Véase también

(C++20) (C++23)
enlaza un número variable de argumentos, en orden, a un objeto función
(plantilla de función)
marcadores de posición para los argumentos no enlazados en una expresión std::bind
(constante)
(C++11)
crea un objeto función a partir de un puntero a miembro
(plantilla de función)