2014-12-05 11 views
5

Uczę się programowania asio biblioteki C++ Boost. I spotkałem wiele przykładów, które używają funkcji bind(), która ma wskaźnik funkcji jako argument.Celem wiązania funkcji

nie są w stanie zrozumieć wykorzystanie wiążą funkcji(). I dlatego mam problemy ze zrozumieniem programów używających asio biblioteki boost.

Nie szukam tutaj żadnego kodu. Po prostu chcę znać użycie funkcji bind() lub dowolnej równoważnej funkcji. Z góry dzięki.

+1

Przekształca ona funkcję w inną, w której ustala się jeden lub więcej (lub zero) argumentów. Na przykład f (x, y) -> f (5, y). – Noel

+0

Przepraszam, ale nie zrozumiałem dobrze. –

+0

może pomóc: http://www.codeproject.com/Articles/13015/A-look-at-the-Boost-Bind-and-Function-libraries – midor

Odpowiedz

4

Z cppreference

Szablon funkcja wiązania wytwarza opakowanie przekazywanie połączeń dla C. Wywołanie tego opakowania jest równoważne wywołaniu f z niektórymi jego argumentami związanymi z args.

Sprawdź example below wykazując Bind

#include <iostream> 
#include <functional> 

using namespace std; 

int my_f(int a, int b) 
{ 
    return 2 * a + b; 
} 

int main() 
{ 
    using namespace std::placeholders; // for _1, _2, _3... 

    // Invert the order of arguments 
    auto my_f_inv = bind(my_f, _2, _1);  // 2 args b and a 
    // Fix first argument as 10 
    auto my_f_1_10 = bind(my_f, 10, _1);  // 1 arg b 
    // Fix second argument as 10 
    auto my_f_2_10 = bind(my_f, _1, 10);  // 1 arg a 
    // Fix both arguments as 10 
    auto my_f_both_10 = bind(my_f, 10, 10);  // no args 

    cout << my_f(5, 15) << endl; // expect 25 
    cout << my_f_inv(5, 15) << endl; // expect 35 
    cout << my_f_1_10(5) << endl; // expect 25 
    cout << my_f_2_10(5) << endl; // expect 20 
    cout << my_f_both_10() << endl; // expect 30 

    return 0; 
} 

Można użyć wiążą się manipulować kolejność argumentów istniejącą funkcję, albo naprawić niektóre argumenty. Może to być szczególnie pomocne w przypadku kontenera STL i algorytmów, w których można przekazać istniejącą funkcję biblioteki bibliotecznej, której sygnatura jest zgodna z wymaganiami.

Na przykład, jeśli chcesz, aby przekształcić wszystkie debla w pojemniku do potęgi 2, można po prostu przejść zrobić coś takiego std::transform(begin(dbl_vec), end(dbl_vec), begin(dbl_vec), std::bind(std::pow, _1, 2))

Live example here

2

Zadania wysyłane do usługi boost::asio muszą być możliwe do zaakceptowania z zerowymi argumentami, aby usługa mogła je przechowywać i wywoływać je, gdy ma wolne zasoby (to znaczy wątłe wątki). Powiedzmy, że chcesz wywołać funkcję void purr(int kitty), aby przekazać ją do usługi w formacie, który może zadziałać, aby powiązać z argumentem kitty funkcji purr. Da ci to obiekt, który jest dostępny do rezerwacji z () bez argumentów, które możesz podać w usłudze.

Oczywiście z C++ 11 i funkcjami lambda najlepszym sposobem na zrobienie tego jest teraz wykonanie io_service.post([&](){ purr(3); }); i unikanie używania łącznie bind.

1

To pozwala skojarzyć (lub „bind”) swój własne dane z funkcją, którą biblioteka ma wywoływać, bez konieczności posiadania przez bibliotekę informacji o danych.

Ponieważ patrzysz Boost.Asio, przyjrzeć się ich tutorial for binding arguments to a handler. Mają funkcji, które chcą używać jako przewodnika, który potrzebuje wskazówek do własnych danych, sam zegar i licznik:

void print(const boost::system::error_code& /*e*/, 
    boost::asio::deadline_timer* t, int* count) 
{ 
    // ... 
} 

async_wait funkcja timera powoduje, funkcję użytkownika pod warunkiem, która ma zostać wywołana, gdy czas wygaśnięcia; ale zapewnia tylko pierwszy z tych argumentów.Handler ma postać

void handler(
    const boost::system::error_code& error // Result of operation. 
); 

Więc możemy użyć bind przekształcić naszą funkcję (chcąc trzy argumenty) na taki, który chce tylko jeden argument, poprzez określenie wartości mają być przekazywane jako dwóch pozostałych:

t.async_wait(boost::bind(print, 
    boost::asio::placeholders::error, &t, &count)); 

Wynik obiektu bind jest obiektem funkcyjnym (tj. Obiektem klasy klasy, który przeciąży operator wywołania funkcji, operator()), który w tym przypadku przyjmuje pojedynczy argument. Argument placeholders::error mówi, że pierwszy argument jest nadal argumentem nowego typu funkcji; pozostałe dwa argumenty otrzymują wartości &t i &count po wywołaniu nowej funkcji. Więc gdybyśmy nazwać siebie:

auto f = boost::bind(print, boost::asio::placeholders::error, &t, &count) 
f(some_error); 

to będzie miało taki sam efekt jak wywołanie pierwotną funkcję z tych argumentów:

print(some_error, &t, &count); 

Teraz, po upływie czasu, nasza funkcja jest wywoływana, z argumentami, które dostarczyliśmy, bez biblioteki Asio, która musi coś o nich wiedzieć.