2009-09-13 15 views
15

Chciałbym nauczyć się korzystać z funkcji wiążących. Oto pomysł: mam tę funkcję, która trwa do parametrów:Jak korzystać z bind1st i bind2nd?

void print_i(int t, std::string separator) 
{ 
     std::cout << t << separator; 
} 

I chciałbym zrobić:

std::vector<int> elements; 
// ... 
for_each(elements.begin(), elements.end(), std::bind2nd(print_i, '\n')); 

Ale to nie działa!

Oto co mam:

/usr/include/c++/4.3/backward/binders.h: In instantiation of ‘std::binder2nd<void()(int, std::string)>’: 
main.cpp:72: instantiated from here 
/usr/include/c++/4.3/backward/binders.h:138: error: ‘void()(int, std::string)’ is not a class, struct, or union type 
/usr/include/c++/4.3/backward/binders.h:141: error: ‘void()(int, std::string)’ is not a class, struct, or union type 
/usr/include/c++/4.3/backward/binders.h:145: error: ‘void()(int, std::string)’ is not a class, struct, or union type 
/usr/include/c++/4.3/backward/binders.h:149: error: ‘void()(int, std::string)’ is not a class, struct, or union type 
/usr/include/c++/4.3/backward/binders.h:155: error: ‘void()(int, std::string)’ is not a class, struct, or union type 
/usr/include/c++/4.3/backward/binders.h:140: error: field ‘std::binder2nd<void()(int, std::string)>::op’ invalidly declared function type 
/usr/include/c++/4.3/backward/binders.h: In function ‘std::binder2nd<_Operation> std::bind2nd(const _Operation&, const _Tp&) [with _Operation = void()(int, std::string), _Tp = char]’: 
main.cpp:72: instantiated from here 
/usr/include/c++/4.3/backward/binders.h:164: error: ‘void()(int, std::string)’ is not a class, struct, or union type 
/usr/include/c++/4.3/bits/stl_algo.h: In function ‘_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, _Funct = std::binder2nd<void()(int, std::string)>]’: 
main.cpp:72: instantiated from here 
/usr/include/c++/4.3/bits/stl_algo.h:3791: error: no match for call to ‘(std::binder2nd<void()(int, std::string)>) (int&)’ 
make: *** [all] Error 1 

mogę użyć funktor, ale jest szybsze w użyciu wiążące.

Dzięki!

+2

Nie jest to związane z pytaniem, więc zamiast tego mały komentarz. Najkrótszy kod wyjściowy zakresu prawdopodobnie kopiuje go do 'ostream_iterator', np. 'std :: copy (v.begin(), v.end(), std :: ostream_iterator (std :: cout," \ n "));'. –

Odpowiedz

11

Argumentem dla bind2nd musi być AdaptableBinaryFunction. Zwykła funkcja binarna nie spełnia tego wymogu (wymagana funkcja przystosowawcza wymagająca typowania w przypadku jej zwracania i typów argumentów, zwykły typ funkcji nie zapewnia żadnych typów). Możesz użyć std::bind, co i tak jest prawdopodobnie lepszym wyborem.

+0

Czy możesz podać mi przykład AdaptableBinaryFunction?
Dzięki – Arthur

+8

'std :: ptr_fun' może konwertować funkcję binarną na' AdaptableBinaryFunction': http://www.sgi.com/tech/stl/ptr_fun.html –

25

Musisz użyć Copyable/Refrencable obiektu, następujące prace:

 
#include <iostream> 
#include <string> 
#include <vector> 
#include <algorithm> 
#include <functional> 

void print_i(int t, std::string separator) 
{ 
    std::cout << t << separator; 
} 

int main() 
{ 
    std::vector<int> elements; 
    std::string delim = "\n"; 
    for_each(elements.begin(), 
      elements.end(), 
      std::bind2nd(std::ptr_fun(&print_i),delim)); 
    return 0; 
} 

Normalnie można uzyskać ten sam efekt, po prostu wykonując następujące czynności:

 
#include <iostream> 
#include <vector> 
#include <algorithm> 
#include <iterator> 

int main() 
{ 
    std::vector<int> elements; 
    std::copy(elements.begin(), 
      elements.end(), 
      std::ostream_iterator<int>(std::cout,"\n")); 
    return 0; 
} 

także zakładając, że masz dostęp do TR1 w STL, którego używasz, zawsze najlepiej jest zmienić/zastąpić wszelkie zastosowania bind1st i bind2nd ze std :: bind

3

Musisz wykonać następujące czynności:
1. utworzyć struct (lub klasy), która dziedziczy std :: binary_function
2. utworzyć czynność źródłowe do operatora() funkcję składową struktury utworzonej w etapie 1
3. Za pomocą bind2nd Wiązanie właściwe wartość do struktury utworzonej w kroku 1

Zrobiłem to wszystko w przykładzie. Możesz przeczytać artykuł i pobrać kompletny kod pod następującym linkiem: bind and find

+2

Witaj w SO! nie wahaj się dołączyć kodu, jest opcja w trybie edycji przycisk wygląda tak: '{}', i mając krótki przykładowy kod explicative jest zawsze dobry, jak 'klasa A {public: operator bool() (const B & b) {doSomething(); return true;} '... tylko przykład :-) –