2013-04-23 38 views
9

Tôi đã chơi arround với std :: function và std :: bind và tôi nhận thấy một cái gì đó không trực quan và tôi muốn hiểu nó tốt hơn.Hiểu std :: function và std :: bind

Ví dụ:

void fun() 
{ 
} 

void hun(std::string) 
{ 
} 

int main() 
{ 

    function<void(int)> g = &fun; //This fails as it should in my understanding. 

    function<void(int)> f = std::bind(fun); //This works for reasons unknown to me  
    function<void(int, std::string)> h = std::bind(hun); //this doesn't work 

return 0; 
} 

Làm thế nào là nó có thể để ràng buộc một function<void(int)> đến một chức năng đó là void(). Sau đó tôi có thể gọi f (1) và vui chơi(). Tôi muốn hiểu cách thực hiện điều này. Đi bên trong Microsoft Visual Studio 2012 thực hiện điều này đã cho tôi bị mất trong một biển của các macro không đọc được. vì vậy đó là lý do tại sao tôi hỏi câu hỏi này ở đây.

+0

Tôi đang sử dụng phiên bản Express2012. – Alex

+0

bạn có thể giới thiệu một trang web như vậy? – Alex

+0

Biên dịch với _clang_ và _g ++ _ cả hai. 1, tình huống thú vị. – soon

Trả lời

7

Nếu bạn không sử dụng trình giữ chỗ đối số (_1, _2, ...), thì bất kỳ đối số nào được truyền cho đối tượng hàm trả về từ std::bind sẽ bị hủy. Với:

std::function<void(int)> f = std::bind(fun, std::placeholders::_1); 

Tôi nhận được lỗi (dài và xấu) như mong đợi.

Đối với những người quan tâm trong Standardese:

§20.8.9.1.2 [func.bind.bind]

template<class F, class... BoundArgs> 
*unspecified* bind(F&& f, BoundArgs&&... bound_args); 

p3 Returns: Một cuộc gọi chuyển tiếp wrapper g với một loại kết quả yếu (20.8.2). Hiệu quả của việc g(u1, u2, ..., uM) sẽ INVOKE(fd, v1, v2, ..., vN, result_of<FD cv (V1, V2, ..., VN)>::type), nơi cv đại diện cho cv -qualifiers của gvà các giá trị và các loại của các đối số ràng buộc v1, v2, ..., vN được xác định theo quy định dưới đây.

p10 Các giá trị của các đối số ràng buộc v1, v2, ..., vN và các loại tương ứng của họ V1, V2, ..., VNphụ thuộc vào các loại TiD có nguồn gốc từ các cuộc gọi đến bindcv -qualifiers cv của cuộc gọi wrapper g như sau:

  • nếu TiDreference_wrapper<T>, các đối số là tid.get() và kiểu của nó ViT&;
  • nếu giá trị của is_bind_expression<TiD>::valuetrue, đối số là tid(std::forward<Uj>(uj)...) và loại của nó là Viresult_of<TiD cv (Uj...)>::type;
  • nếu giá trị j của is_placeholder<TiD>::value không phải là 0, đối số là std::forward<Uj>(uj) và loại của nó ViUj&&;
  • nếu không, giá trị là tid và loại của nó ViTiD cv &.
+0

Thêm vào đó, ngay cả khi std :: function f = std :: bind (vui); biên dịch. Không thể thực sự gọi f: f(); không biên dịch được. –

+1

@PeterR: Rõ ràng, vì chữ ký để 'f' ủy nhiệm một đối số. :) – Xeo

6

Trình bao bọc cuộc gọi chuyển tiếp được tạo bởi cuộc gọi đến mẫu chức năng bind có thể chấp nhận bất kỳ số tham số phụ nào; những điều này sẽ bị bỏ qua. Hiệu ứng tinh khiết và chữ ký tối thiểu của một biểu thức bind được xác định bởi các placeholder s được sử dụng trong xây dựng của nó, và đối số có thể gọi được (s) họ đang bị ràng buộc.

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