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* )
Definiert im Header <functional>
std::bind_front
template < class F, class ... Args >
constexpr /* unspecified */ bind_front ( F && f, Args && ... args ) ;
(1) (seit C++20)
template < auto ConstFn, class ... Args >
constexpr /* unspecified */ bind_front ( Args && ... args ) ;
(2) (seit C++26)
std::bind_back
template < class F, class ... Args >
constexpr /* unspecified */ bind_back ( F && f, Args && ... args ) ;
(3) (seit C++23)
template < auto ConstFn, class ... Args >
constexpr /* unspecified */ bind_back ( Args && ... args ) ;
(4) (seit C++26)

Funktionsvorlagen std::bind_front und std::bind_back erzeugen einen perfekten Weiterleitungs-Aufrufwrapper, der es ermöglicht, das aufrufbare Ziel mit seinen (1,2) ersten oder (3,4) letzten sizeof... ( Args ) Parametern an args gebunden aufzurufen.

1,3) Der Aufruf-Wrapper hält eine Kopie des Ziel-aufrufbaren Objekts f .
2,4) Der Aufrufwrapper enthält kein aufrufbares Ziel (dies ist statisch bestimmt).
1) std :: bind_front ( f, bound_args... ) ( call_args... ) ist ausdrucksäquivalent zu
std:: invoke ( f, bound_args..., call_args... ) .
2) std :: bind_front < ConstFn > ( bound_args... ) ( call_args... ) ist ausdrucksäquivalent zu
std:: invoke ( ConstFn, bound_args..., call_args... ) .
3) std :: bind_back ( f, bound_args... ) ( call_args... ) ist ausdrucksäquivalent zu
std:: invoke ( f, call_args..., bound_args... ) .
4) std :: bind_back < ConstFn > ( bound_args... ) ( call_args... ) ist ausdrucksäquivalent zu
std:: invoke ( ConstFn, call_args..., bound_args... ) .

Die folgenden Bedingungen müssen true sein, andernfalls ist das Programm fehlerhaft:

Inhaltsverzeichnis

Parameter

f - Callable Objekt (Funktionsobjekt, Funktionszeiger, Funktionsreferenz, Zeiger auf Elementfunktion oder Zeiger auf Datenelement), das an einige Argumente gebunden wird
args - Liste der Argumente, die an die ( 1,2 ) ersten oder ( 3,4 ) letzten sizeof... ( Args ) Parameter des aufrufbaren Ziels gebunden werden
Typanforderungen
-
std:: decay_t < F > muss die Anforderungen von MoveConstructible erfüllen.
-
std:: decay_t < Args > ... muss die Anforderungen von MoveConstructible erfüllen.
-
decltype ( ConstFn ) muss die Anforderungen von Callable erfüllen.

Rückgabewert

Ein Funktionsobjekt (der Aufruf-Wrapper) vom Typ T , der nicht näher spezifiziert ist, außer dass die Typen der Objekte, die von zwei Aufrufen von std::bind_front oder std::bind_back mit denselben Argumenten zurückgegeben werden, gleich sind.

Lassen Sie bind-partial entweder std::bind_front oder std::bind_back sein.

Das zurückgegebene Objekt hat folgende Eigenschaften:

bind-partial Rückgabetyp

Member-Objekte

Das zurückgegebene Objekt verhält sich so, als ob es Folgendes enthält:

1,3) Ein Mitgliedsobjekt fd vom Typ std:: decay_t < F > direkt-nicht-Listen-initialisiert von std:: forward < F > ( f ) , und
1-4) Ein std::tuple -Objekt tup konstruiert mit std:: tuple < std:: decay_t < Args > ... > ( std:: forward < Args > ( args ) ... ) , mit der Ausnahme, dass das Zuweisungsverhalten des zurückgegebenen Objekts nicht spezifiziert ist und die Namen nur zur Veranschaulichung dienen.

Konstruktoren

Der Rückgabetyp von bind-partial verhält sich so, als ob seine Kopier-/Verschiebekonstruktoren eine elementweise Kopie/Verschiebung durchführen. Er ist CopyConstructible wenn alle seine Mitgliedsobjekte (wie oben spezifiziert) CopyConstructible sind, andernfalls ist er MoveConstructible .

Member-Funktion operator()

Gegeben ein Objekt G erhalten von einem früheren Aufruf von ( 1,3 ) bind-partial (f, args...) oder ( 2,4 ) bind-partial <ConstFn>(args...) , wenn ein Glvalue g das G bezeichnet in einem Funktionsaufrufausdruck g ( call_args... ) aufgerufen wird, findet eine Aufruf des gespeicherten Objekts statt, als ob durch:

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

wo

  • Ns ist eine Integer-Pack 0, 1, ..., (sizeof...(Args) - 1) ,
  • g ist ein Lvalue im std::invoke -Ausdruck, wenn es ein Lvalue im Aufrufausdruck ist, andernfalls ist es ein Rvalue. Daher kann std :: move ( g ) ( call_args... ) die gebundenen Argumente in den Aufruf verschieben, während g ( call_args... ) kopieren würde.

Das Programm ist fehlerhaft, wenn g einen volatile-qualifizierten Typ hat.

Der Member operator ( ) ist noexcept wenn der std::invoke Ausdruck, den er aufruft, noexcept ist (mit anderen Worten, er bewahrt die Ausnahmespezifikation des zugrundeliegenden Aufrufoperators).

Ausnahmen

1,3) Wirft jede Ausnahme, die durch den Aufruf des Konstruktors des gespeicherten Funktionsobjekts ausgelöst wird.
1-4) Wirft jede Ausnahme, die durch den Aufruf des Konstruktors eines der gebundenen Argumente ausgelöst wird.

Hinweise

Diese Funktionsvorlagen sollen std::bind ersetzen. Im Gegensatz zu std::bind unterstützen sie keine beliebige Neuordnung von Argumenten und haben keine spezielle Behandlung für verschachtelte Bind-Ausdrücke oder std::reference_wrapper s. Andererseits berücksichtigen sie die Wertkategorie des Aufrufwrapper-Objekts und propagieren die Ausnahmespezifikation des zugrundeliegenden Aufrufoperators.

Wie in std::invoke beschrieben, muss beim Aufruf eines Zeigers auf eine nicht-statische Member-Funktion oder eines Zeigers auf ein nicht-statisches Datenmitglied das erste Argument eine Referenz oder ein Zeiger (einschließlich möglicherweise intelligenter Zeiger wie std::shared_ptr und std::unique_ptr ) auf ein Objekt sein, auf dessen Mitglied zugegriffen wird.

Die Argumente für std::bind_front oder std::bind_back werden kopiert oder verschoben und niemals als Referenz übergeben, es sei denn, sie sind in std::ref oder std::cref eingewickelt.

Typischerweise erfordert das Binden von Argumenten an eine Funktion oder eine Memberfunktion mit ( 1 ) std::bind_front und ( 3 ) std::bind_back das Speichern eines Funktionszeigers zusammen mit den Argumenten, obwohl die Sprache genau weiß, welche Funktion aufgerufen werden soll, ohne dass der Zeiger dereferenziert werden muss. Um in diesen Fällen "Zero Cost" zu garantieren, führt C++26 die Versionen ( 2,4 ) ein (die das aufrufbare Objekt als Argument für constant template parameter akzeptieren).

Feature-Test Makro Wert Std Funktion
__cpp_lib_bind_front 201907L (C++20) std::bind_front , ( 1 )
202306L (C++26) Erlaubt das Übergeben von aufrufbaren Objekten als konstante Template-Argumente an std::bind_front , ( 2 )
__cpp_lib_bind_back 202202L (C++23) std::bind_back , ( 3 )
202306L (C++26) Erlaubt das Übergeben von aufrufbaren Objekten als konstante Template-Argumente an std::bind_back , ( 4 )

Mögliche Implementierung

(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> oder 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 { /* ist gleich wie oben */ }
template<auto ConstFn, class... Args>
constexpr auto bind_back(Args&&... args)
{
    using F = decltype(ConstFn);
    if constexpr (std::is_pointer_v<F> oder 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)...);
        };
}

Beispiel

#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); // entspricht: 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
    // Noexcept-Spezifikation bleibt erhalten:
    static_assert(!noexcept(fifty_minus(3)));
    static_assert(noexcept(member_minus(3)));
    // Bindung einer Lambda-Funktion:
    auto plus = [](int a, int b) { return a + b; };
    auto forty_plus = std::bind_front(plus, 40);
    assert(forty_plus(7) == 47); // entspricht: 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
}

Referenzen

  • C++26-Standard (ISO/IEC 14882:2026):
  • TBD Funktionsvorlagen bind_front und bind_back [func.bind.partial]
  • C++23-Standard (ISO/IEC 14882:2024):
  • 22.10.14 Funktionsvorlagen bind_front und bind_back [func.bind.partial]
  • C++20-Standard (ISO/IEC 14882:2020):
  • 20.14.14 Funktionsvorlage bind_front [func.bind.front]

Siehe auch

(C++11)
bindet ein oder mehrere Argumente an ein Funktionsobjekt
(Funktions-Template)
(C++11)
erstellt ein Funktionsobjekt aus einem Zeiger auf ein Mitglied
(Funktions-Template)