2009-09-13 21 views
15

Tôi muốn tìm hiểu cách sử dụng các chức năng liên kết. Dưới đây là ý tưởng: tôi có chức năng này mà mất các thông số:Cách sử dụng bind1st và bind2nd?

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

Và tôi muốn làm:

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

Nhưng nó không hoạt động!

Dưới đây là những gì tôi nhận được:

/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 

tôi có thể sử dụng functor, nhưng nó là nhanh hơn để sử dụng ràng buộc.

Cảm ơn!

+2

Nó không liên quan đến câu hỏi, vì vậy, hãy nhận xét nhỏ. Mã ngắn nhất để xuất một dải có thể sao chép nó thành 'ostream_iterator', ví dụ: 'std :: copy (v.begin(), v.end(), std :: ostream_iterator (std :: cout," \ n "));'. –

Trả lời

11

Đối số cho bind2nd phải là AdaptableBinaryFunction. Một hàm nhị phân thuần túy không đáp ứng yêu cầu này (một hàm thích hợp được yêu cầu typedef cho các kiểu đối số và trả về của nó, một kiểu hàm đơn giản không cung cấp bất kỳ typedef nào). Bạn có thể sử dụng std::bind mà có lẽ là sự lựa chọn tốt hơn anyway.

+0

Bạn có thể cho tôi một ví dụ về AdaptableBinaryFunction không?
Cảm ơn – Arthur

+8

'std :: ptr_fun' có thể chuyển đổi chức năng nhị phân thành' AdaptableBinaryFunction': http://www.sgi.com/tech/stl/ptr_fun.html –

25

Bạn cần phải sử dụng một/đối tượng Refrencable copyable, các công việc sau:

 
#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; 
} 

Thông thường bạn có thể nhận được tác dụng tương tự bằng cách đơn giản làm như sau:

 
#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; 
} 

Cũng giả sử bạn có quyền truy cập để TR1 trong STL bạn đang sử dụng, luôn luôn tốt nhất để sửa đổi/thay thế bất kỳ sử dụng nào của bind1st và bind2nd bằng std :: bind

3

Bạn cần thực hiện các bước sau:
1. tạo cấu trúc (hoặc lớp) thừa kế từ std :: binary_function
2. xác định hàm vị ngữ của bạn trong hàm operator() thành viên của cấu trúc được tạo trong bước 1
3. sử dụng bind2nd để liên kết giá trị cho cấu trúc được tạo ở bước 1

Tôi đã làm tất cả điều này trong ví dụ. Bạn có thể đọc bài viết và tải xuống mã hoàn chỉnh trên liên kết sau: bind and find

+2

Chào mừng bạn đến với SO! đừng ngần ngại bao gồm mã, có một tùy chọn trong chế độ chỉnh sửa nút trông giống như: '{}', và có một đoạn mã giải thích ngắn luôn luôn là tốt, như 'class A {public: bool operator() (const B & b) {doSomething(); return '}' ... chỉ là một ví dụ :-) –

Các vấn đề liên quan