2012-05-23 25 views
16

Làm cách nào tôi có thể liên kết với một hàm nhận đối số mặc định, mà không chỉ định các đối số mặc định và sau đó gọi nó mà không có bất kỳ đối số nào?Tôi có thể liên kết với một hàm có đối số mặc định và sau đó gọi nó không?

void foo(int a, int b = 23) { 
    std::cout << a << " " << b << std::endl; 
} 

int main() { 
    auto f = std::bind(foo, 23, 34); // works 
    f(); 


    auto g = std::bind(foo, 23); // doesn't work 
    g(); 

    using std::placeholders::_1; 
    auto h = std::bind(foo, 23, _1); // doesn't work either 
    h(); 

} 
+1

Xác định "không hoạt động". Mã sẽ biên dịch nếu bạn đặt tên khác nhau cho các biến. –

+0

tại sao bạn tiếp tục chuyển nhượng lại cho f? – 111111

+0

@ R.MartinhoFernandes vâng xin lỗi, ví dụ không đầy đủ. mã được cập nhật – inf

Trả lời

20

Về cơ bản, bất kỳ lúc nào bạn viết trình biên dịch sẽ dịch thành foo(x, 23);. Nó chỉ hoạt động nếu bạn thực sự có một cuộc gọi trực tiếp với tên hàm. Bạn không thể, ví dụ: chỉ định &foo cho một số void(*)(int), bởi vì chữ ký của hàm là void(int, int). Các tham số mặc định không phát một phần nào trong chữ ký. Và nếu bạn gán nó cho biến số void(*)(int, int), thông tin về tham số mặc định bị mất: bạn không thể tận dụng thông số mặc định thông qua biến đó. std::bind lưu trữ void(*)(int, int) ở đâu đó trong ruột của nó và do đó mất thông tin tham số mặc định.

Không có cách nào trong C++ để nhận giá trị mặc định của tham số từ bên ngoài hàm, do đó bạn bị mắc kẹt với việc cung cấp giá trị mặc định theo cách thủ công khi bạn liên kết.

+0

nền tảng tuyệt vời, cảm ơn. – inf

8

Tôi nghĩ bạn có thể mô phỏng hành vi bạn muốn bằng lambda.

cái gì đó dọc theo dòng này:

auto g = [](){ foo(23); }; 

EDIT: Chỉ cần kiểm tra, và dường như làm việc tốt: http://ideone.com/SPSvi

0

Tôi có hai giải pháp:

1 - Bạn có thể quá tải foo () và gọi cho bản gốc bằng các giá trị mặc định:

void foo(int a, int b) 
{ 
    std::cout << a << " " << b << std::endl; 
} 

inline void foo(int a) 
{ 
    foo(a, 23); 
} 

2 - Bạn có thể sử dụng một biến tĩnh như mặc định và sau đó sử dụng nó trong quá trình liên kết:

static int foo_default_b = 23; 
void foo(int a, int b = foo_default_b) 
{ 
    std::cout << a << " " << b << std::endl; 
} 

auto g = std::bind(foo, 23, foo_default_b); 
g(); 
0

This answer không đồng ý với R. Martinho Fernandes' câu trả lời. Bạn thực sự có thể sử dụng boost::bind liên kết với các thông số mặc định, bạn chỉ cần đặt giữ chỗ ở, như vậy:

boost::bind<void (int, int)>(foo, _1, _2)(12); 

này sẽ gọi foo(12, 23), như mong đợi. Mặc dù tôi đã không kiểm tra mã cụ thể này, tôi đã thực hiện một cái gì đó tương tự trong mã của tôi dựa trên câu trả lời được liên kết ở trên, và nó hoạt động trong gcc 4.8.5.

Hmm, tôi vừa nhận thấy rằng đây là yêu cầu về std::bind, không phải boost::bind. Tôi không biết có sự khác biệt nào, nếu có.

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