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* )
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 .

1,3) Le wrapper d'appel détient une copie de l'objet appelable cible f .
2,4) L'enveloppe d'appel ne détient pas de cible appelable (cela est déterminé statiquement).
1) std :: bind_front ( f, bound_args... ) ( call_args... ) est expression-équivalent à
std:: invoke ( f, bound_args..., call_args... ) .
2) std :: bind_front < ConstFn > ( bound_args... ) ( call_args... ) est équivalent en expression à
std:: invoke ( ConstFn, bound_args..., call_args... ) .
3) std :: bind_back ( f, bound_args... ) ( call_args... ) est équivalent en expression à
std:: invoke ( f, call_args..., bound_args... ) .
4) std :: bind_back < ConstFn > ( bound_args... ) ( call_args... ) est équivalent en expression à
std:: invoke ( ConstFn, call_args..., bound_args... ) .

Les conditions suivantes doivent être true , sinon le programme est mal formé :

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 :

1,3) Un objet membre fd de type std:: decay_t < F > initialisé par initialisation directe non-liste à partir de std:: forward < F > ( f ) , et
1-4) Un objet std::tuple 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 :

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

  • Ns est un pack d'entiers 0, 1, ..., (sizeof...(Args) - 1) ,
  • g est 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

1,3) Lance toute exception levée par l'appel au constructeur de l'objet fonction stocké.
1-4) Lance toute exception levée par l'appel du constructeur de l'un des arguments liés.

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)