Namespaces
Variants

std:: bind

From cppreference.net
Utilities library
Function objects
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>
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 Funktionsvorlage std::bind erzeugt einen weiterleitenden Aufruf-Wrapper für f . Das Aufrufen dieses Wrappers ist gleichbedeutend mit dem Aufruf von f mit einigen seiner Argumente gebunden an args .

Wenn std:: is_constructible < std:: decay < F > :: type , F > :: value gleich false ist, oder std:: is_constructible < std:: decay < Arg_i > :: type , Arg_i > :: value gleich false für irgendeinen Typ Arg_i in Args ist, dann ist das Programm fehlerhaft.

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

Inhaltsverzeichnis

Parameter

f - Callable Objekt (Funktionsobjekt, Zeiger auf Funktion, Referenz auf Funktion, Zeiger auf Memberfunktion oder Zeiger auf Datenelement), das an einige Argumente gebunden wird
args - Liste der zu bindenden Argumente, wobei die ungebundenen Argumente durch die Platzhalter _1 , _2 , _3 ... des Namespace std::placeholders ersetzt werden

Rückgabewert

Ein Funktionsobjekt g eines nicht näher spezifizierten Typs T , für das std:: is_bind_expression < T > :: value gleich true ist. Es besitzt die folgenden Member:

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 ) , sowie ein Objekt für jedes der 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 seiner Member-Objekte (wie oben spezifiziert) CopyConstructible sind, andernfalls ist er MoveConstructible . Der Typ definiert die folgenden Member:

Member type result_type

1) (deprecated in C++17) Wenn F ein Zeiger auf eine Funktion oder ein Zeiger auf eine Elementfunktion ist, ist result_type der Rückgabetyp von F . Wenn F ein Klassentyp mit verschachteltem typedef result_type ist, dann ist result_type gleich F::result_type . Andernfalls ist kein result_type definiert.
2) (deprecated in C++17) result_type ist exakt R .
(bis C++20)

Member-Funktion operator()

Wenn g in einem Funktionsaufrufausdruck g ( u1, u2, ... uM ) aufgerufen wird, erfolgt ein Aufruf des gespeicherten Objekts, 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 wie unten spezifiziert bestimmt werden.

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

Ein Aufruf von operator ( ) ist nicht-werfend oder ist ein konstanter Teilausdruck (seit C++20) genau dann, wenn die zugrundeliegende INVOKE -Operation dies ist. operator ( ) nimmt an der Überladungsauflösung nur teil, wenn die INVOKE -Operation wohlgeformt ist, wenn sie als nicht-ausgewerteter Operand behandelt wird.

Wenn g mit volatile qualifiziert ist, ist das Programm fehlerhaft.

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

Gebundene Argumente

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

Fall 1: Referenz-Wrapper

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

Fall 2: Bind-Ausdrücke

Wenn arg_i vom Typ T ist, für den std:: is_bind_expression < T > :: value gleich true ist (z.B. wenn ein anderer std::bind -Ausdruck direkt in den ursprünglichen Aufruf von std::bind übergeben wurde), dann führt std::bind Funktionskomposition durch: Anstatt das Funktionsobjekt zu übergeben, das der Bind-Subausdruck zurückgeben würde, wird der Subausdruck sofort ausgewertet und sein Rückgabewert an das äußere aufrufbare Objekt übergeben. Wenn der Bind-Subausdruck Platzhalterargumente enthält, werden diese mit dem äußeren Bind geteilt (ausgewählt aus u1 , u2 , ... ). Konkret ist v_i gleich 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) (CV-Qualifikation ist identisch mit der von g ).

Fall 3: placeholders

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 im ursprünglichen Aufruf von std::bind verwendet), dann wird das durch den Platzhalter angegebene 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&& .

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 die gleiche CV-Qualifikation wie die von g ist.

Exceptions

Wirft nur, wenn die Konstruktion von std:: decay < F > :: type aus std:: forward < F > ( f ) wirft, oder 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.

Hinweise

Wie in Callable beschrieben, muss beim Aufruf eines Zeigers auf eine nicht-statische Member-Funktion oder eines Zeigers auf ein nicht-statisches Datenelement 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 Member zugegriffen wird.

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

Doppelte Platzhalter im selben Bind-Ausdruck (mehrere _1 zum Beispiel) sind erlaubt, aber die Ergebnisse sind nur wohldefiniert, wenn das entsprechende Argument ( u1 ) ein Lvalue oder ein nicht bewegbarer Rvalue ist.

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;  // für _1, _2, _3...
    std::cout << "1) Argument-Reihenfolgeänderung und Pass-by-Reference: ";
    int n = 7;
    // (_1 und _2 stammen aus std::placeholders und repräsentieren zukünftige
    // Argumente, die an f1 übergeben werden)
    auto f1 = std::bind(f, _2, 42, _1, std::cref(n), n);
    n = 10;
    f1(1, 2, 1001); // 1 wird durch _1 gebunden, 2 wird durch _2 gebunden, 1001 wird nicht verwendet
                    // führt einen Aufruf von f(2, 42, 1, n, 7) aus
    std::cout << "2) Erzielen des gleichen Effekts mit einem 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); // dasselbe wie ein Aufruf von f1(1, 2, 1001)
    std::cout << "3) verschachtelte Bind-Subausdrücke teilen sich die Platzhalter: ";
    auto f2 = std::bind(f, _3, std::bind(g, _3), _3, 4, 5);
    f2(10, 11, 12); // führt einen Aufruf von f(12, g(12), 12, 4, 5) aus;
    std::cout << "4) binden Sie einen Zufallszahlengenerator mit einer Verteilung: ";
    std::default_random_engine e;
    std::uniform_int_distribution<> d(0, 10);
    auto rnd = std::bind(d, e); // eine Kopie von e wird in rnd gespeichert
    for (int n = 0; n < 10; ++n)
        std::cout << rnd() << ' ';
    std::cout << '\n';
    std::cout << "5) an einen Zeiger auf eine Member-Funktion binden: ";
    Foo foo;
    auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1);
    f3(5);
    std::cout << "6) Bindung an ein mem_fn, das ein Zeiger auf eine Member-Funktion ist: ";
    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) Bindung an einen Zeiger auf ein Datenmitglied: ";
    auto f5 = std::bind(&Foo::data, _1);
    std::cout << f5(foo) << '\n';
    std::cout << "8) an ein mem_fn binden, das ein Zeiger auf ein Datenmitglied ist: ";
    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) Verwenden Sie Smart Pointer, um Member der referenzierten Objekte aufzurufen: ";
    std::cout << f6(std::make_shared<Foo>(foo)) << ' '
              << f6(std::make_unique<Foo>(foo)) << '\n';
}

Ausgabe:

1) Argumenten-Umordnung und Pass-by-Reference: 2 42 1 10 7
2) Erzielen des gleichen Effekts mit einem Lambda: 2 42 1 10 7
3) Verschachtelte Bind-Subausdrücke teilen sich die Platzhalter: 12 12 12 4 5
4) Binden eines RNG mit einer Verteilung: 0 1 8 5 5 2 0 7 7 10 
5) Binden an einen Zeiger auf eine Member-Funktion: 100
6) Binden an ein mem_fn, das ein Zeiger auf eine Member-Funktion ist: 100
7) Binden an einen Zeiger auf ein Datenmitglied: 10
8) Binden an ein mem_fn, das ein Zeiger auf ein Datenmitglied ist: 10
9) Verwenden von Smart Pointern zum Aufruf von Membern der referenzierten Objekte: 10 10

Fehlerberichte

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

DR Angewendet auf Verhalten wie veröffentlicht Korrektes Verhalten
LWG 2021 C++11 1. die gebundenen Argumente
wurden nicht an fd weitergeleitet
2. in 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 &&

Siehe auch

(C++20) (C++23)
bindet eine variable Anzahl von Argumenten in einer bestimmten Reihenfolge an ein Funktionsobjekt
(Funktions-Template)
Platzhalter für die ungebundenen Argumente in einem std::bind -Ausdruck
(Konstante)
(C++11)
erstellt ein Funktionsobjekt aus einem Zeiger auf ein Element
(Funktions-Template)