2011-08-30 24 views
15

Tôi đã quen với cú pháp nhìn thấy như thế này cho con trỏ hàmCú pháp của C++ mẫu với các thông số loại chức năng

int (*pointer_name) (float, char *); 
void call_function (void (*)(int), int); 

Trong một số C++ 03 thư viện chức năng tôi thấy loại được sử dụng theo cách này:

abc::function<void(*)(int,float)> f; 

Trong C++ 11 của std::function tôi thấy loại nhường chỗ này

std::function<void(int,float)> f; 

có một thiếu (*). Tại sao?

C++ 03 function<T>T là một loại giống hệt với con trỏ hàm tương ứng. Thật dễ dàng để tưởng tượng việc thực hiện.

std::function trong C++ 11 được hỗ trợ bởi các cải tiến ngôn ngữ cốt lõi. Có các loại đối số mẫu được mở rộng để đáp ứng khả năng gọi không?

Trả lời

17

std::function (và nguồn cảm hứng, boost::function) không chỉ lưu trữ con trỏ hàm. Nó cũng có thể lưu trữ các đối tượng hàm. Theo nghĩa đó, hãy chuyển một chữ ký chức năng làm thông số mẫu tương tự như cách con trỏ thông minh lấy loại thông số pointee làm thông số mẫu chứ không phải kiểu con trỏ!

Contrast:

int* p; // indirection to an object of type int 
std::unique_ptr<int> q; // indirection to an object of type int 

với

typedef void signature_type(); // a function type 

// indirection to something callable with signature_type as a signature 
// i.e. f() has type void 
// only work for freestanding functions however 
signature_type* f; 

// indirection to something callable with signature_type as a signature 
// i.e. g() has type void 
// not restricted to function pointers! 
std::function<signature_type> g; 

Đây là một quy ước hữu ích.

+0

Điều này đẹp hơn rất nhiều so với cú pháp con trỏ tới sách giáo khoa! Tôi tự hỏi tại sao chúng ta không dạy nó theo cách này bình thường ... – spraff

+1

@spraff: Có lẽ vì nó là một sự đổi mới tương đối gần đây, và hầu hết các sách giáo khoa đều có doanh thu rất chậm. Tôi vẫn thấy những người học với Borland Turbo C++, mà dường như có rất nhiều rắc rối với cú pháp này. – greyfade

3

Các loại chức năng không phải là mới trong C++ 11 (xem 8.3.5 trong C++ 98). IIRC, sự cải thiện so với những gì TR1 và tăng cung cấp cho function là khá nhỏ.

8

Không có gì kỳ diệu là ở đây, loại

void(int,float) 

là loại một chức năng mà không có tên. Nó khớp với một hàm như void g(int x, float y).

Với mẫu bạn không để sử dụng con trỏ hàm, bạn cũng có thể sử dụng các loại chức năng.

8

Giống như với các phần tử khác, các hàm có một loại và bạn có thể sử dụng loại hoặc con trỏ đến loại trong các ngữ cảnh khác nhau. Thiếu (*) bạn đang mong đợi chỉ là cú pháp của cú pháp trỏ tới.

int (*pointer_name) (float, char *); 
typedef int my_function_type(float,char*); 
my_function_type * pointer_name2; 

Các loại pointer_namepointer_name2 đều giống nhau: con trỏ tới một hàm trả về int và nhận hai đối số của các loại floatchar*.Lưu ý rằng điều này là chính xác tương đương với các loại khác như int, với sự khác biệt mà bạn không thể khai báo biến là loại chức năng, chỉ con trỏ đến hàm.

Giao diện của std::function (hoặc boost::function) chỉ cần ký chữ ký của hàm. Đối số loại không phải là con trỏ để hoạt động mà là loại hàm (như my_function_type trong mã ở trên)

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