std:: bind
|
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
|
(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
INVOKE
(
fd,
std::
forward
<
V1
>
(
v1
)
,
std::
forward
<
V2
>
(
v2
)
, ...,
std::
forward
<
VN
>
(
vN
)
)
, ou
INVOKE<R>
(
fd,
std::
forward
<
V1
>
(
v1
)
,
std::
forward
<
V2
>
(
v2
)
, ...,
std::
forward
<
VN
>
(
vN
)
)
,
`, `
` 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.
où
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) |
|
(C++11)
|
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) |