Namensräume
Varianten
Aktionen

std::bind

Von cppreference.com
< cpp‎ | utility‎ | functional
 
 
Dienstprogramm-Bibliotheken
Sprachunterstützung
Typunterstützung (Basistypen, RTTI)
Bibliotheks-Feature-Test-Makros (C++20)
Programm-Dienstprogramme
Variadische Funktionen
Coroutine-Unterstützung (C++20)
Vertragsunterstützung (C++26)
Drei-Wege-Vergleich
(C++20)
(C++20)(C++20)(C++20)  
(C++20)(C++20)(C++20)

Allgemeine Hilfsmittel
Relationale Operatoren (in C++20 veraltet)
 
Funktionsobjekte
Funktionsaufruf
(C++17)(C++23)
Identitätsfunktions-Objekt
(C++20)
Transparente Operator-Wrapper
(C++14)
(C++14)
(C++14)
(C++14)  
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)

Alte Binder und Adaptoren
(bis C++17*)
(bis C++17*)
(bis C++17*)
(bis C++17*)
(bis C++17*)(bis C++17*)(bis C++17*)(bis C++17*)
(bis C++20*)
(bis C++20*)
(bis C++17*)(bis C++17*)
(bis C++17*)(bis C++17*)

(bis C++17*)
(bis C++17*)(bis C++17*)(bis C++17*)(bis C++17*)
(bis C++20*)
(bis C++20*)
 
Definiert in der Header-Datei <functional>
template< class F, class... Args >
/* unspecified */ bind( F&& f, Args&&... args );
(1) (seit C++11)
(constexpr seit C++20)
template< class R, class F, class... Args >
/* unspecified */ bind( F&& f, Args&&... args );
(2) (seit C++11)
(constexpr seit C++20)

Die Funktionvorlage std::bind generiert einen Weiterleitungsaufruf-Wrapper für f. Das Aufrufen dieses Wrappers entspricht dem Aufrufen von f mit einigen seiner Argumente, die an args gebunden sind.

Wenn std::is_constructible<std::decay<F>::type, F>::value false ist oder std::is_constructible<std::decay<Arg_i>::type, Arg_i>::value für einen Typ Arg_i in Args false ist, ist das Programm schlecht geformt.

Wenn std::decay<Ti>::type oder ein Typ in Args nicht MoveConstructible oder Destructible ist, ist das Verhalten undefiniert.

Inhalt

[edit] Parameter

f - Aufrufbares Objekt (Funktionsobjekt, Zeiger auf Funktion, Referenz auf Funktion, Zeiger auf Mitgliedsfunktion oder Zeiger auf Datenmitglied), das an einige Argumente gebunden wird
args - Liste von Argumenten, die gebunden werden sollen, wobei die ungebundenen Argumente durch die Platzhalter _1, _2, _3... im Namensraum std::placeholders ersetzt werden

[edit] Rückgabewert

Ein Funktionsobjekt g eines nicht spezifizierten Typs T, für das std::is_bind_expression<T>::value true ist. Es hat die folgenden Mitglieder:

std::bind Rückgabetyp

Member-Objekte

Der Rückgabetyp von std::bind enthält ein Mitgliedsobjekt vom Typ std::decay<F>::type, konstruiert aus std::forward<F>(f), und ein Objekt für jedes der Argumente args... vom Typ std::decay<Arg_i>::type, ähnlich konstruiert aus std::forward<Arg_i>(arg_i).

Konstruktoren

Der Rückgabetyp von std::bind ist CopyConstructible, wenn alle seine Mitgliedsobjekte (wie oben angegeben) CopyConstructible sind, und andernfalls MoveConstructible. Der Typ definiert die folgenden Mitglieder:

Mitgliedstyp result_type

1) (in C++17 veraltet) Wenn F ein Zeiger auf eine Funktion oder ein Zeiger auf eine Mitgliedsfunktion ist, ist result_type der Rückgabetyp von F. Wenn F ein Klassentyp mit der verschachtelten Typedef result_type ist, dann ist result_type F::result_type. Andernfalls ist kein result_type definiert.
2) (in C++17 veraltet) result_type ist exakt R.
(bis C++20)

Member-Funktionsoperator ()

Wenn g in einem Funktionsaufruf-Ausdruck g(u1, u2, ... uM) aufgerufen wird, findet ein Aufruf des gespeicherten Objekts statt, als ob durch:

1) INVOKE(fd, std::forward<V1>(v1), std::forward<V2>(v2), ..., std::forward<VN>(vN)) oder
2) INVOKE<R>(fd, std::forward<V1>(v1), std::forward<V2>(v2), ..., std::forward<VN>(vN)),

wobei fd ein Wert vom Typ std::decay<F>::type ist, die Werte und Typen der gebundenen Argumente v1, v2, ..., vN gemäß der Spezifikation unten bestimmt werden.

Wenn einige der Argumente, die im Aufruf an g() übergeben werden, nicht durch Platzhalter in g abgedeckt werden, werden die ungenutzten Argumente ausgewertet und verworfen.

Ein Aufruf von operator() ist nicht auslösend oder ist ein konstanter Teilausdruck(seit C++20), wenn und nur wenn der zugrunde liegende INVOKE-Vorgang nicht auslösend ist. operator() nimmt nur an der Auflösung von Überladungen teil, wenn der INVOKE-Vorgang als nicht ausgewerteter Operand wohlgeformt ist.

Wenn g volatile-qualifiziert ist, ist das Programm schlecht geformt.

Wenn INVOKE(fd, w1, w2, ..., wN) niemals ein gültiger Ausdruck für beliebige mögliche Werte w1, w2, ..., wN sein kann, ist das Verhalten undefiniert.

[edit] Gebundene Argumente

Für jedes gespeicherte Argument arg_i wird das entsprechende gebundene Argument v_i im INVOKE- oder INVOKE<R>-Vorgang wie folgt bestimmt:

[edit] Fall 1: Referenz-Wrapper

Wenn arg_i vom Typ std::reference_wrapper<T> ist (z. B. wenn std::ref oder std::cref im ursprünglichen Aufruf von std::bind verwendet wurde), dann ist v_i arg_i.get() und sein Typ V_i ist T&: Das gespeicherte Argument wird per Referenz an das aufgerufene Funktionsobjekt übergeben.

[edit] Fall 2: Bind-Ausdrücke

Wenn arg_i vom Typ T ist, für den std::is_bind_expression<T>::value true ist (z. B. ein weiterer std::bind-Ausdruck wurde direkt in den ursprünglichen Aufruf von std::bind übergeben), dann führt std::bind eine Funktionskomposition durch: Anstatt das Funktionsobjekt zurückzugeben, das der Bind-Teilausdruck zurückgeben würde, wird der Teilausdruck sofort aufgerufen und sein Rückgabewert an das äußere aufrufbare Objekt übergeben. Wenn der Bind-Teilausdruck Platzhalterargumente hat, werden diese mit dem äußeren Bind geteilt (aus u1, u2, ... ausgewählt). Insbesondere ist v_i arg_i(std::forward<Uj>(uj)...) und sein Typ V_i ist std::result_of<T cv &(Uj&&...)>::type&&(bis C++17)std::invoke_result_t<T cv &, Uj&&...>&&(seit C++17) (Die cv-Qualifikation ist dieselbe wie bei g).

[edit] Fall 3: Platzhalter

Wenn arg_i vom Typ T ist, für den std::is_placeholder<T>::value nicht 0 ist (d. h., ein Platzhalter wie std::placeholders::_1, _2, _3, ... wurde als Argument für den ursprünglichen Aufruf von std::bind verwendet), dann wird das durch den Platzhalter angezeigte Argument (u1 für _1, u2 für _2 usw.) an das aufrufbare Objekt übergeben: v_i ist std::forward<Uj>(uj) und sein Typ V_i ist Uj&&.

[edit] Fall 4: Gewöhnliche Argumente

Andernfalls wird arg_i als lvalue-Argument an das aufrufbare Objekt übergeben: v_i ist einfach arg_i und sein Typ V_i ist T cv &, wobei cv dieselbe cv-Qualifikation wie die von g ist.

[edit] Ausnahmen

Wirft nur, wenn die Konstruktion von std::decay<F>::type aus std::forward<F>(f) wirft, oder wenn einer der Konstruktoren für std::decay<Arg_i>::type aus dem entsprechenden std::forward<Arg_i>(arg_i) wirft, wobei Arg_i der i-te Typ und arg_i das i-te Argument in Args... args ist.

[edit] Hinweise

Wie in Callable beschrieben, muss beim Aufrufen eines Zeigers auf eine nicht-statische Mitgliedsfunktion oder eines Zeigers auf ein nicht-statisches Datenmitglied das erste Argument eine Referenz oder ein Zeiger (einschließlich möglicherweise eines Smart Pointers wie std::shared_ptr und std::unique_ptr) auf ein Objekt sein, dessen Mitglied zugegriffen werden soll.

Die Argumente für bind werden kopiert oder verschoben und niemals per Referenz übergeben, es sei denn, sie sind in std::ref oder std::cref verpackt.

Doppelte Platzhalter im selben Bind-Ausdruck (z. B. mehrere _1) sind zulässig, aber die Ergebnisse sind nur dann wohldefiniert, wenn das entsprechende Argument (u1) ein lvalue oder ein nicht verschiebbares rvalue ist.

[edit] Beispiel

#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;  // for _1, _2, _3...
 
    std::cout << "1) argument reordering and pass-by-reference: ";
    int n = 7;
    // (_1 and _2 are from std::placeholders, and represent future
    // 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 is bound by _1, 2 is bound by _2, 1001 is unused
                    // makes a call to f(2, 42, 1, n, 7)
 
    std::cout << "2) achieving the same effect using a lambda: ";
    n = 7;
    auto lambda = [&ncref = n, n](auto a, auto b, auto /*unused*/)
    {
        f(b, 42, a, ncref, n);
    };
    n = 10;
    lambda(1, 2, 1001); // same as a call to f1(1, 2, 1001)
 
    std::cout << "3) nested bind subexpressions share the placeholders: ";
    auto f2 = std::bind(f, _3, std::bind(g, _3), _3, 4, 5);
    f2(10, 11, 12); // makes a call to f(12, g(12), 12, 4, 5);
 
    std::cout << "4) bind a RNG with a distribution: ";
    std::default_random_engine e;
    std::uniform_int_distribution<> d(0, 10);
    auto rnd = std::bind(d, e); // a copy of e is stored in rnd
    for (int n = 0; n < 10; ++n)
        std::cout << rnd() << ' ';
    std::cout << '\n';
 
    std::cout << "5) bind to a pointer to member function: ";
    Foo foo;
    auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1);
    f3(5);
 
    std::cout << "6) bind to a mem_fn that is a pointer to member function: ";
    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) bind to a pointer to data member: ";
    auto f5 = std::bind(&Foo::data, _1);
    std::cout << f5(foo) << '\n';
 
    std::cout << "8) bind to a mem_fn that is a pointer to data member: ";
    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) use smart pointers to call members of the referenced objects: ";
    std::cout << f6(std::make_shared<Foo>(foo)) << ' '
              << f6(std::make_unique<Foo>(foo)) << '\n';
}

Ausgabe

1) argument reordering and pass-by-reference: 2 42 1 10 7
2) achieving the same effect using a lambda: 2 42 1 10 7
3) nested bind subexpressions share the placeholders: 12 12 12 4 5
4) bind a RNG with a distribution: 0 1 8 5 5 2 0 7 7 10 
5) bind to a pointer to member function: 100
6) bind to a mem_fn that is a pointer to member function: 100
7) bind to a pointer to data member: 10
8) bind to a mem_fn that is a pointer to data member: 10
9) use smart pointers to call members of the referenced objects: 10 10

[edit] Fehlermeldungen

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
LWG 2021 C++11 1. die gebundenen Argumente
    wurden nicht an fd weitergeleitet
2. im Fall 2 war der Typ von V_i
    std::result_of<T cv (Uj...)>::type
1. weitergeleitet
2. geändert zu
    std::result_of<T cv &(Uj&&...)>::type&&

[edit] Siehe auch

(C++20)(C++23)
bindet eine variable Anzahl von Argumenten, in Reihenfolge, an ein Funktions-Objekt
(Funktions-Template) [bearbeiten]
Platzhalter für die ungebundenen Argumente in einem std::bind-Ausdruck
(Konstante) [bearbeiten]
(C++11)
erstellt ein Funktions-Objekt aus einem Zeiger auf ein Member
(Funktions-Template) [bearbeiten]