2012-04-16 18 views
9
int __cdecl ccall(int i) 
{ 
    wprintf(L"ccall(%d)", i); 
    return 0; 
} 

int __stdcall stdcall(int i) 
{ 
    wprintf(L"stdcall(%d)", i); 
    return 0; 
} 

int __cdecl wmain(int argc, wchar_t **argv) 
{ 
    std::function<int(int)> fnc = ccall; 
    std::function<int(int)> fnstd = stdcall; 

    fnc(10); // printed well 
    fnstd(100); // printed well 
    return 0; 
} 

Tôi đã quan tâm làm cách nào để chỉ định đối tượng __stdcall function cho std::function. Nhưng không có bất kỳ quy ước cụ thể nào, có vẻ như hoạt động tốt. Làm thế nào có thể std::function biết quy ước gọi là gì?Làm thế nào để std :: function biết về quy ước gọi điện thoại?

+2

Trong cùng một cách trình biên dịch biết làm thế nào để gọi hàm mà không cần 'std :: function'. 'std :: function' sử dụng type-erasure để tạo ra một hộp đen nhỏ bên trong, khi bạn gọi hàm' std :: function' được yêu cầu thực hiện cuộc gọi "thực", mà trình biên dịch đã tìm ra. – GManNickG

Trả lời

6

std::function có thể lưu trữ các con trỏ hàm sử dụng bất kỳ quy ước gọi nào.

§ 20.8.11.2:

Chức năng lớp mẫu cung cấp giấy gói đa hình mà khái quát khái niệm về một con trỏ hàm. Các trình bao bọc có thể lưu trữ, sao chép và gọi các đối tượng có thể gọi được (20.8.1), được gán một chữ ký cuộc gọi (20.8.1), cho phép các hàm trở thành đối tượng lớp đầu tiên.

Như John Calsbeekadded: Không có gì đặc biệt trong các tiêu chuẩn liên quan đến các công ước gọi là, nhưng trình biên dịch đang làm công việc của họ và con trỏ hàm chứa các thông tin về hội nghị.

Với chức năng gợi ý bạn sẽ cần phải xác định quy ước gọi bất thường:

typedef int(* c_ptr_t)(int); 
typedef int(__stdcall * std_ptr_t)(int); 

c_ptr_t c_ptr = ccall; 
std_ptr_t std_ptr = stdcall; 

// But std::function doesn't mind: 
std::function<int(int)> fnc = c_ptr; 
std::function<int(int)> fnstd = std_ptr; 
+5

Tôi không chắc chắn đây là một câu trả lời về mặt kỹ thuật, vì tiêu chuẩn C++ hầu như không đề cập đến quy ước gọi điện, và nó chắc chắn không có ở đây. Câu trả lời là 'std :: function'" nhớ "loại hàm sử dụng ma thuật xóa kiểu, và hàm con trỏ trong các trình biên dịch hợp lý nhất chứa thông tin về quy ước gọi được sử dụng. –

+0

@JohnCalsbeek: Bạn nói đúng, không có gì chi tiết hơn trong tiêu chuẩn hơn là đề cập đến phần được trích dẫn. Các quy ước gọi là một lãnh thổ chưa được thám hiểm, nhưng các trình biên dịch được xử lý tốt và thực hiện những gì cần thiết. – Anonymous

+2

Điều gần nhất là "liên kết C". Có trình biên dịch chỉ có để làm cho nó hoạt động - không có gì trong tiêu chuẩn mà làm cho các lập trình viên chịu trách nhiệm. Bằng cách mở rộng, vì tiêu chuẩn không nói gì về việc gọi các quy ước, sự im lặng đó lại làm cho nó trở thành trách nhiệm biên dịch. – MSalters

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