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* )
Défini dans l'en-tête <functional>
template < class F, class ... Args >
/* non spécifié */ bind ( F && f, Args && ... args ) ;
(1) (depuis C++11)
(constexpr depuis C++20)
template < class R, class F, class ... Args >
/* non spécifié */ bind ( F && f, Args && ... args ) ;
(2) (depuis C++11)
(constexpr depuis C++20)

Le modèle de fonction std::bind génère un wrapper d'appel de transfert pour f . L'appel de ce wrapper équivaut à invoquer f avec certains de ses arguments liés à args .

Si std:: is_constructible < std:: decay < F > :: type , F > :: value est false , ou si std:: is_constructible < std:: decay < Arg_i > :: type , Arg_i > :: value est false pour tout type Arg_i dans Args , le programme est mal formé.

Si std:: decay < Ti > :: type ou tout type dans Args n'est pas MoveConstructible ou Destructible , le comportement est indéfini.

Table des matières

Paramètres

f - Callable objet appelable (objet fonction, pointeur vers fonction, référence vers fonction, pointeur vers fonction membre, ou pointeur vers membre de données) qui sera lié à certains arguments
args - liste d'arguments à lier, avec les arguments non liés remplacés par les substituts _1 , _2 , _3 ... de l'espace de noms std::placeholders

Valeur de retour

Un objet fonction g de type non spécifié T , pour lequel std:: is_bind_expression < T > :: value est true . Il possède les membres suivants :

std::bind type de retour

Objets membres

Le type de retour de std::bind contient un objet membre de type std:: decay < F > :: type construit à partir de std:: forward < F > ( f ) , et un objet pour chacun des args... , de type std:: decay < Arg_i > :: type , construit de manière similaire à partir de std:: forward < Arg_i > ( arg_i ) .

Constructeurs

Le type de retour de std::bind est CopyConstructible si tous ses objets membres (spécifiés ci-dessus) sont CopyConstructible, et est MoveConstructible sinon. Le type définit les membres suivants :

Type membre result_type

1) (obsolète en C++17) Si F est un pointeur vers une fonction ou un pointeur vers une fonction membre, result_type est le type de retour de F . Si F est un type classe avec un typedef imbriqué result_type , alors result_type est F::result_type . Sinon, aucun result_type n'est défini.
2) (obsolète en C++17) result_type est exactement R .
(jusqu'en C++20)

Fonction membre operator()

Lorsque g est invoqué dans une expression d'appel de fonction g ( u1, u2, ... uM ) , un appel de l'objet stocké a lieu, comme par

1) INVOKE ( fd, std:: forward < V1 > ( v1 ) , std:: forward < V2 > ( v2 ) , ..., std:: forward < VN > ( vN ) ) , ou
2) INVOKE<R> ( fd, std:: forward < V1 > ( v1 ) , std:: forward < V2 > ( v2 ) , ..., std:: forward < VN > ( vN ) ) ,
**Note:** Le code C++ contenu dans les balises ` `, `
` et `` n'a pas été traduit conformément aux instructions, car il s'agit de code technique spécifique au C++ qui doit rester inchangé. Seul le texte en dehors de ces balises a été traduit en français.

fd est une valeur de type std:: decay < F > :: type , les valeurs et types des arguments liés v1 , v2 , ..., vN sont déterminés comme spécifié ci-dessous .

Si certains des arguments fournis dans l'appel à g ( ) ne correspondent à aucun des espaces réservés stockés dans g , les arguments inutilisés sont évalués puis ignorés.

Un appel de operator ( ) est non-lanceur ou est une sous-expression constante (depuis C++20) si et seulement si l'opération sous-jacente INVOKE l'est également. operator ( ) participe à la résolution de surcharge uniquement si l'opération INVOKE est bien formée lorsqu'elle est traitée comme un opérande non évalué.

Si g est qualifié volatile , le programme est mal formé.

Si INVOKE ( fd, w1, w2, ..., wN ) ne peut jamais être une expression valide pour aucune valeur possible w1 , w2 , ..., wN , le comportement est indéfini.

Arguments liés

Pour chaque argument stocké arg_i , l'argument lié correspondant v_i dans l'opération INVOKE ou INVOKE<R> est déterminé comme suit :

Cas 1 : reference wrappers

Si arg_i est de type std:: reference_wrapper < T > (par exemple, std::ref ou std::cref a été utilisé dans l'appel initial à std::bind ), alors v_i est arg_i. get ( ) et son type V_i est T& : l'argument stocké est passé par référence à l'objet fonction invoqué.

Cas 2 : expressions de liaison

Si arg_i est de type T pour lequel std:: is_bind_expression < T > :: value est true (par exemple, une autre expression std::bind a été passée directement dans l'appel initial à std::bind ), alors std::bind effectue une composition de fonctions : au lieu de passer l'objet fonction que la sous-expression bind retournerait, la sous-expression est évaluée immédiatement, et sa valeur de retour est passée à l'objet invocable externe. Si la sous-expression bind a des arguments d'espace réservé, ils sont partagés avec le bind externe (sélectionnés parmi u1 , u2 , ... ). Plus précisément, v_i est arg_i ( std:: forward < Uj > ( uj ) ... ) et son type V_i est std:: result_of < T cv  & ( Uj && ... ) > :: type && (jusqu'à C++17) std:: invoke_result_t < T cv  & , Uj && ... > && (depuis C++17) (la qualification cv est la même que celle de g ).

Cas 3 : placeholders

Si arg_i est de type T , pour lequel std:: is_placeholder < T > :: value n'est pas 0 (ce qui signifie qu'un espace réservé tel que std::placeholders::_1, _2, _3, ... a été utilisé comme argument lors de l'appel initial à std::bind ), alors l'argument indiqué par l'espace réservé ( u1 pour _1 , u2 pour _2 , etc.) est passé à l'objet invocable : v_i est std:: forward < Uj > ( uj ) et son type V_i est Uj&& .

Cas 4 : arguments ordinaires

Sinon, arg_i est passé à l'objet invocable comme argument lvalue : v_i est simplement arg_i et son type V_i est T cv  & , où cv est la même qualification cv que celle de g .

Exceptions

Ne lance que si la construction de std:: decay < F > :: type à partir de std:: forward < F > ( f ) lance, ou si l'un des constructeurs pour std:: decay < Arg_i > :: type à partir du std:: forward < Arg_i > ( arg_i ) correspondant lance, où Arg_i est le ième type et arg_i est le ième argument dans Args... args .

Notes

Comme décrit dans Callable , lors de l'invocation d'un pointeur vers une fonction membre non statique ou d'un pointeur vers un membre de données non statique, le premier argument doit être une référence ou un pointeur (incluant, éventuellement, un pointeur intelligent tel que std::shared_ptr et std::unique_ptr ) vers un objet dont le membre sera accédé.

Les arguments passés à bind sont copiés ou déplacés, et ne sont jamais passés par référence à moins d'être encapsulés dans std::ref ou std::cref .

Les espaces réservés dupliqués dans la même expression de liaison (plusieurs _1 par exemple) sont autorisés, mais les résultats ne sont bien définis que si l'argument correspondant ( u1 ) est une lvalue ou une rvalue non déplaçable.

Exemple

#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;  // pour _1, _2, _3...
    std::cout << "1) réorganisation des arguments et passage par référence : ";
    int n = 7;
    // (_1 et _2 proviennent de std::placeholders, et représentent des
    // arguments that will be passed to f1)
    auto f1 = std::bind(f, _2, 42, _1, std::cref(n), n);
    n = 10;
    f1(1, 2, 1001); // 1 est lié par _1, 2 est lié par _2, 1001 n'est pas utilisé
                    // effectue un appel à f(2, 42, 1, n, 7)
    std::cout << "2) obtenir le même effet en utilisant une lambda : ";
    n = 7;
    auto lambda = [&ncref = n, n](auto a, auto b, auto /*inutilisé*/)
    {
        f(b, 42, a, ncref, n);
    };
    n = 10;
    lambda(1, 2, 1001); // identique à un appel à f1(1, 2, 1001)
    std::cout << "3) les sous-expressions de liaison imbriquées partagent les espaces réservés : ";
    auto f2 = std::bind(f, _3, std::bind(g, _3), _3, 4, 5);
    f2(10, 11, 12); // effectue un appel à f(12, g(12), 12, 4, 5);
    std::cout << "4) lier un GNA avec une distribution : ";
    std::default_random_engine e;
    std::uniform_int_distribution<> d(0, 10);
    auto rnd = std::bind(d, e); // une copie de e est stockée dans rnd
    for (int n = 0; n < 10; ++n)
        std::cout << rnd() << ' ';
    std::cout << '\n';
    std::cout << "5) liaison à un pointeur vers une fonction membre: ";
    Foo foo;
    auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1);
    f3(5);
    std::cout << "6) lier à un mem_fn qui est un pointeur vers une fonction membre: ";
    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) liaison à un pointeur vers un membre de données : ";
    auto f5 = std::bind(&Foo::data, _1);
    std::cout << f5(foo) << '\n';
    std::cout << "8) lier à un mem_fn qui est un pointeur vers un membre de données : ";
    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) utilisez des pointeurs intelligents pour appeler les membres des objets référencés : ";
    std::cout << f6(std::make_shared<Foo>(foo)) << ' '
              << f6(std::make_unique<Foo>(foo)) << '\n';
}

Sortie :

1) réorganisation des arguments et passage par référence : 2 42 1 10 7
2) obtenir le même effet en utilisant une lambda : 2 42 1 10 7
3) les sous-expressions bind imbriquées partagent les placeholders : 12 12 12 4 5
4) lier un GNA avec une distribution : 0 1 8 5 5 2 0 7 7 10 
5) lier à un pointeur vers une fonction membre : 100
6) lier à un mem_fn qui est un pointeur vers une fonction membre : 100
7) lier à un pointeur vers un membre de données : 10
8) lier à un mem_fn qui est un pointeur vers un membre de données : 10
9) utiliser des pointeurs intelligents pour appeler les membres des objets référencés : 10 10

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Applicable à Comportement publié Comportement corrigé
LWG 2021 C++11 1. les arguments liés
n'étaient pas transmis à fd
2. dans le cas 2, le type de V_i était
std:: result_of < T cv  ( Uj... ) > :: type
1. transmis
2. modifié en
std:: result_of < T cv  & ( Uj && ... ) > :: type &&

Voir aussi

(C++20) (C++23)
lie un nombre variable d'arguments, dans l'ordre, à un objet fonction
(modèle de fonction)
espaces réservés pour les arguments non liés dans une expression std::bind
(constante)
(C++11)
crée un objet fonction à partir d'un pointeur vers un membre
(modèle de fonction)