std:: bind_front, std:: bind_back
|
Défini dans l'en-tête
<functional>
|
||
std::bind_front
|
||
|
template
<
class
F,
class
...
Args
>
constexpr /* unspecified */ bind_front ( F && f, Args && ... args ) ; |
(1) | (depuis C++20) |
|
template
<
auto
ConstFn,
class
...
Args
>
constexpr /* unspecified */ bind_front ( Args && ... args ) ; |
(2) | (depuis C++26) |
std::bind_back
|
||
|
template
<
class
F,
class
...
Args
>
constexpr /* unspecified */ bind_back ( F && f, Args && ... args ) ; |
(3) | (depuis C++23) |
|
template
<
auto
ConstFn,
class
...
Args
>
constexpr /* unspecified */ bind_back ( Args && ... args ) ; |
(4) | (depuis C++26) |
Les modèles de fonction
std::bind_front
et
std::bind_back
génèrent un wrapper d'appel à transfert parfait qui permet d'invoquer la cible appelable avec ses
(1,2)
premiers ou
(3,4)
derniers
sizeof...
(
Args
)
paramètres liés à
args
.
Les conditions suivantes doivent être true , sinon le programme est mal formé :
- (1,3) std:: is_constructible_v < std:: decay_t < F > , F > ,
- (1,3) std:: is_move_constructible_v < std:: decay_t < F >> ,
-
(2,4)
Si
decltype
(
ConstFn
)
est un pointeur ou un pointeur-vers-membre alors
ConstFnn'est pas un pointeur nul, - ( std:: is_constructible_v < std:: decay_t < Args > , Args > && ... ) ,
- ( std:: is_move_constructible_v < std:: decay_t < Args >> && ... ) .
Table des matières |
Paramètres
| f | - | Callable objet (fonction objet, pointeur vers fonction, référence vers fonction, pointeur vers fonction membre, ou pointeur vers donnée membre) qui sera lié à certains arguments |
| args | - | liste des arguments à lier aux ( 1,2 ) premiers ou ( 3,4 ) derniers sizeof... ( Args ) paramètres de la cible appelable |
| Exigences de type | ||
-
std::
decay_t
<
F
>
doit satisfaire aux exigences de
MoveConstructible
.
|
||
-
std::
decay_t
<
Args
>
...
doit satisfaire aux exigences de
MoveConstructible
.
|
||
-
decltype
(
ConstFn
)
doit satisfaire aux exigences de
Callable
.
|
||
Valeur de retour
Un objet fonction (le wrapper d'appel) de type
T
qui n'est pas spécifié, sauf que les types d'objets retournés par deux appels à
std::bind_front
ou
std::bind_back
avec les mêmes arguments sont identiques.
Soit
bind-partial
soit
std::bind_front
ou
std::bind_back
.
L'objet retourné possède les propriétés suivantes :
bind-partial type de retour
Objets membres
L'objet retourné se comporte comme s'il contenait :
fd
de type
std::
decay_t
<
F
>
initialisé par initialisation directe non-liste à partir de
std::
forward
<
F
>
(
f
)
, et
tup
construit avec
std::
tuple
<
std::
decay_t
<
Args
>
...
>
(
std::
forward
<
Args
>
(
args
)
...
)
, sauf que le comportement d'affectation de l'objet retourné n'est pas spécifié et les noms sont uniquement à titre d'exposition.
Constructeurs
Le type de retour de
bind-partial
se comporte comme si ses constructeurs de copie/déplacement effectuaient une copie/déplacement membre par membre. Il est
CopyConstructible
si tous ses objets membres (spécifiés ci-dessus) sont
CopyConstructible
, et est
MoveConstructible
sinon.
Fonction membre
operator()
Étant donné un objet
G
obtenu d'un appel antérieur à
(
1,3
)
bind-partial
(f, args...)
ou
(
2,4
)
bind-partial
<ConstFn>(args...)
, lorsqu'une glvalue
g
désignant
G
est invoquée dans une expression d'appel de fonction
g
(
call_args...
)
, un appel de l'objet stocké a lieu, comme par :
bind-partial
est
std::bind_front
,
bind-partial
est
std::bind_front
,
bind-partial
est
std::bind_back
,
bind-partial
est
std::bind_back
,
où
-
-
Nsest un pack d'entiers0, 1, ..., (sizeof...(Args) - 1), -
gest une lvalue dans l'expression std::invoke si c'est une lvalue dans l'expression d'appel, et est une rvalue sinon. Ainsi std :: move ( g ) ( call_args... ) peut déplacer les arguments liés dans l'appel, alors que g ( call_args... ) copierait.
-
Le programme est mal formé si
g
a un type qualifié volatile.
Le membre operator ( ) est noexcept si l'expression std::invoke qu'il appelle est noexcept (en d'autres termes, il préserve la spécification d'exception de l'opérateur d'appel sous-jacent).
Exceptions
Notes
Ces modèles de fonction sont destinés à remplacer
std::bind
. Contrairement à
std::bind
, ils ne prennent pas en charge la réorganisation arbitraire des arguments et n'ont pas de traitement spécial pour les expressions d'encapsulation imbriquées ou les
std::reference_wrapper
. En revanche, ils tiennent compte de la catégorie de valeur de l'objet wrapper d'appel et propagent la spécification d'exception de l'opérateur d'appel sous-jacent.
Comme décrit dans std::invoke , lors de l'appel 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, des pointeurs intelligents tels que std::shared_ptr et std::unique_ptr ) vers un objet dont le membre sera accédé.
Les arguments passés à
std::bind_front
ou
std::bind_back
sont copiés ou déplacés, et ne sont jamais passés par référence sauf s'ils sont encapsulés dans
std::ref
ou
std::cref
.
Typiquement, lier des arguments à une fonction ou à une fonction membre en utilisant
(
1
)
std::bind_front
et
(
3
)
std::bind_back
nécessite de stocker un pointeur de fonction ainsi que les arguments, même si le langage sait précisément quelle fonction appeler sans avoir besoin de déréférencer le pointeur. Pour garantir un coût nul dans ces cas, C++26 introduit les versions
(
2,4
)
(qui acceptent l'objet appelable comme argument pour
paramètre de modèle constant
).
| Macro de test de fonctionnalité | Valeur | Std | Fonctionnalité |
|---|---|---|---|
__cpp_lib_bind_front
|
201907L
|
(C++20) |
std::bind_front
,
(
1
)
|
202306L
|
(C++26) |
Permettre de passer des objets appelables comme arguments template constants à
std::bind_front
,
(
2
)
|
|
__cpp_lib_bind_back
|
202202L
|
(C++23) |
std::bind_back
,
(
3
)
|
202306L
|
(C++26) |
Permettre de passer des objets appelables comme arguments template constants à
std::bind_back
,
(
4
)
|
Implémentation possible
| (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> ou 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 { /* est identique à ci-dessus */ } template<auto ConstFn, class... Args> constexpr auto bind_back(Args&&... args) { using F = decltype(ConstFn); if constexpr (std::is_pointer_v<F> ou 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)...); }; } |
Exemple
#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); // équivalent à : 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 spécification noexcept est préservée : static_assert(!noexcept(fifty_minus(3))); static_assert(noexcept(member_minus(3))); // Liaison d'une lambda : auto plus = [](int a, int b) { return a + b; }; auto forty_plus = std::bind_front(plus, 40); assert(forty_plus(7) == 47); // équivalent à : 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 }
Références
- Norme C++26 (ISO/IEC 14882:2026) :
-
- À déterminer - Modèles de fonction bind_front et bind_back [func.bind.partial]
- Norme C++23 (ISO/IEC 14882:2024) :
-
- 22.10.14 Modèles de fonction bind_front et bind_back [func.bind.partial]
- Norme C++20 (ISO/CEI 14882:2020) :
-
- 20.14.14 Modèle de fonction bind_front [func.bind.front]
Voir aussi
|
(C++11)
|
lie un ou plusieurs arguments à un objet fonction
(modèle de fonction) |
|
(C++11)
|
crée un objet fonction à partir d'un pointeur vers un membre
(modèle de fonction) |