2011-11-10 43 views
11
int func(int x){return x;} 
... 
std::function<int(int)> x = std::bind(func, std::placeholders::_1); 
x(123); 
  1. Liệu x(123) thực sự gọi operator() của functor mà std::function tạo ra nó sẽ gọi các operator() của functor mà std::bind tạo ra mà cuối cùng gọi func? Điều này có được tối ưu hóa thành thứ gì đó tối ưu như gọi số func(123) không?
  2. Functor sống ở đâu mà std::bind tạo ra? Trong phạm vi nào? Và làm thế nào để std::bind đặt tên? (có thể có va chạm tên)
  3. Lambdas có thể thay thế tất cả các công dụng của std::bind?
  4. Có phải std::bind là tối ưu khi triển khai nó dưới dạng lambda thay thế?
  5. Có gì với cú pháp của đối số mẫu là std::function? Làm thế nào để có được phân tích cú pháp và làm thế nào tôi có thể sử dụng cú pháp đối số khuôn mẫu đó ở nơi khác?
+2

Đối với 2. bạn có thể quan tâm đến http://www.artima.com/cppsource/type_erasure.html – Flexo

+4

Một câu hỏi tại một thời điểm, vui lòng. Mỗi bài SO là một câu hỏi. –

+0

Đây là một tập hợp các câu hỏi hơn là một câu hỏi cụ thể, và chúng nằm trong phạm vi từ cú pháp (đối số 'hàm <>') đến hành vi (kết quả của ràng buộc trực tiếp? Lambda có thể thay thế chúng?) nó được tối ưu hóa?) –

Trả lời

16

Liệu x (123) thực sự gọi tổng đài() của functor mà std :: function tạo ra mà lần lượt gọi các nhà điều hành() của functor mà std :: bind tạo ra mà cuối cùng gọi func? Điều này có được tối ưu hóa thành một cái gì đó tối ưu như gọi func (123) không?

Tôi sẽ không mô tả operator() của std::function là 'được tạo' (đó là thành viên thông thường), nhưng nếu không thì đó là mô tả tốt. Tối ưu hóa là tùy thuộc vào trình biên dịch của bạn, nhưng được cảnh báo rằng để tối ưu hóa sự gián đoạn của std::function (yêu cầu sử dụng loại tẩy xoá), trình biên dịch có thể cần phải thực hiện các anh hùng.

Trường hợp functor sống có std :: bind tạo ra? Trong phạm vi nào? Và làm thế nào để std :: bind đặt tên cho nó? (Có thể có tên va chạm)

Các cuộc gọi đến std::bind trả về một functor loại không xác định, và một bản sao của functor được lưu trữ bên trong đối tượng x. Bản sao này sẽ tồn tại miễn là x chính nó. Không có tên liên quan vì vậy tôi không chắc chắn những gì bạn có nghĩa là do đó.

Lambdas có thể thay thế tất cả các công dụng của std :: bind không?

số xem xét auto bound = std::bind(functor, _1); nơi functor là một loại với một quá tải operator(), chúng ta hãy nói về longint. Sau đó bound(0L) không có tác dụng tương tự như bound(0) và bạn không thể sao chép bằng lambda.

Có phải std :: ràng buộc tối ưu như triển khai dưới dạng lambda thay thế không?

Điều này tùy thuộc vào trình biên dịch. Tự đo.

Có gì với cú pháp của đối số mẫu của std :: function? Làm thế nào để có được phân tích cú pháp và làm thế nào tôi có thể sử dụng cú pháp đối số khuôn mẫu đó ở nơi khác?

Đây là loại chức năng. Có lẽ bạn đã quen với cú pháp cho con trỏ/tham chiếu đến hàm: void(*)(), int(&)(double). Sau đó, chỉ cần loại bỏ con trỏ/tham chiếu ra khỏi loại, và bạn chỉ cần có một loại chức năng: void(), int(double). Bạn có thể sử dụng những người như vậy:

typedef int* function_type(long); 
function_type* p; // pointer to function 
+2

+1 cho câu trả lời đúng cho câu hỏi # 2: một functor chỉ là một đối tượng, không có thế hệ lớp ma thuật nào liên quan. –

+1

Đóng đinh sự đa hình tĩnh (liên kết) so với nguyên mẫu monomorhic (hàm <>) khác biệt trong vòng đầu tiên :) Khá là một sự khác biệt sâu sắc nhưng dễ bị bỏ qua. (Bạn đã +1 của tôi ngay từ đầu) – sehe

+0

+1 cho trường hợp sử dụng 'bind' không thể được sao chép bằng lambda. –

6

1.x(123) thực sự gọi số operator() của functor mà std::function được tạo mà lần lượt gọi số operator() của functor mà std::bind tạo ra cuối cùng gọi là func? Điều này có được tối ưu hóa thành thứ gì đó tối ưu như gọi số func(123) không?

Nếu bạn đã bật tối ưu hóa, 'nội dung' được nội tuyến và bạn có thể dựa vào điều này là tối ưu như gọi func(123).

2. Functor sống ở đâu mà std::bind tạo ra? Trong phạm vi nào? Và làm thế nào để std::bind đặt tên? (có thể có sự va chạm tên)

Precising: bind tạo biểu thức ràng buộc, thực hiện được xác định, ràng buộc, có thể gán cho function<>. Chức năng chỉ là một mẫu lớp (Cảm ơn, Luc T.). Và nó sống trong thư viện chuẩn. Tuy nhiên, các biểu thức ràng buộc được thực hiện xác định.

Thư viện chuẩn không đi kèm với các đặc điểm (std::is_bind_expression<>) để cho phép phát hiện MPL các biểu thức như vậy. Một tính năng quyết định của các biểu thức kết buộc trên std :: function là chúng là (những gì tôi gọi) các đối tượng có thể gọi được (tức là chúng giữ nguyên ngữ nghĩa của trang gọi bao gồm khả năng chọn quá tải tại trang ứng dụng thực tế). Mặt khác, std::function<> cam kết với một nguyên mẫu đơn lẻ và lưu trữ nội bộ callable object theo kiểu xóa (nghĩ variant hoặc any).

3. Lambdas có thể thay thế tất cả các công dụng của std :: bind?

4. Là std :: ràng buộc tối ưu như thực hiện nó như là một lambda thay thế?

AFAICT lambdas nên biên dịch về tương tự như biểu thức ràng buộc. Một điều mà tôi nghĩ lambdas không thể làm điều đó biểu thức ràng buộc thểnested bind expressions Sửa Trong khi thành ngữ cụ thể của biểu thức ràng buộc lồng nhau được không replicatable sử dụng lambdas, lambdas là tất nhiên có thể thể hiện (gần) cùng nhiều tự nhiên hơn:

bind(f, bind(g, _1))(x); 
// vs. 
[](int x) { f(g(x)); }; 

 

5. Có gì với cú pháp của đối số mẫu là std::function? Làm thế nào để có được phân tích cú pháp và làm thế nào tôi có thể sử dụng cú pháp đối số khuôn mẫu đó ở nơi khác?

Nó chỉ là chữ ký hàm (loại của hàm), được chuyển làm tham số mẫu.

Bạn cũng có thể sử dụng nó làm kiểu tham số chức năng, làm giảm thành con trỏ hàm (tương tự như cách tham số mảng theo giá trị phân tách thành con trỏ, Cảm ơn David!). Trên thực tế, bất cứ nơi nào nhất, miễn là bạn không có nhu cầu tên một biến/loại:

void receiveFunction(void(int, double)); // spunky 'function<>'-style syntax 

void sample(int, double) { } 

int main() 
{ 
    receiveFunction(sample); 
} 

void receiveFunction(void (*f)(int, double)) // boring 'old' style syntax 
//     void (f)(int, double) // ... also ok 
{ 
    // .. 
} 
+0

Giả sử 'f' và' g' không bị quá tải, thì biểu thức liên kết lồng nhau có thể được biểu diễn dưới dạng lambda: '[] (T t) {return f (g (t)); } '. –

+0

@LucDanton: tìm thấy thông tin trong câu trả lời của bạn. 1 cho rằng – sehe

+1

Tôi không đồng ý ở điểm 2: câu trả lời đúng là không có functor "được tạo ra" bởi 'bind', chỉ là một đối tượng tạm thời được trả về bởi một hàm, không có tên và sẽ tồn tại trong thời gian biểu thức nó xuất hiện trong (giống như tất cả các thời gian). Tạm thời này được sử dụng để khởi tạo 'x'. –

0

lambdas có thể thay thế tất cả các công dụng của std :: ràng buộc?

C++ 14 sẽ cho phép lambda hầu như thay thế liên kết. Đáp ứng đặc biệt cho câu trả lời của Luc Danton, trong C++ 14, bạn có thể viết lambdas templated bằng cách sử dụng tự động sao cho bound(0)bound(0L) hoạt động khác nhau.

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