2012-06-19 27 views
12

xem xét mẫu chức năng này:suy ra mẫu đối số từ std :: chức năng gọi chữ ký

template<typename ReturnT> 
ReturnT foo(const std::function<ReturnT()>& fun) 
{ 
    return fun(); 
} 

Tại sao không phải là nó có thể cho trình biên dịch để suy luận ReturnT từ chữ ký cuộc gọi thông qua?

bool bar() { /* ... */ } 

foo<bool>(bar); // works 
foo(bar); // error: no matching function call 
+1

Câu trả lời cho [một trong các câu hỏi trước của tôi] (http://stackoverflow.com/questions/9625526/check-at-compile-time-if-template-argument-is-void) cho phép loại cú pháp này. Tôi hy vọng rằng sẽ giúp. Đó là trường hợp đặc biệt trong trường hợp loại trả về cũng bị vô hiệu. – chris

+0

@chris Cảm ơn gợi ý - Tôi sẽ cố gắng hiểu nó :) –

+0

N.B. rất giống với http://stackoverflow.com/q/7608741/981959 và http://stackoverflow.com/q/9242234/981959, nhưng tôi nghĩ câu trả lời ở đây rõ ràng hơn cho câu hỏi cụ thể này. –

Trả lời

7
std::function<bool()> bar; 

foo(bar); // works just fine 

C++ không thể suy ra kiểu trả về từ hàm của bạn bar vì nó sẽ phải biết loại trước khi nó có thể tìm thấy tất cả các nhà thầu mà đưa con trỏ hàm của bạn.

Ví dụ: ai là người nói rằng std::function<std::string()> không có nhà xây dựng tham gia bool (*)()?

0

Chức năng bar là loại bool (*)() hoặc lâu hơn, đó là: một bình thường trước C++ loại 11 chức năng. Tôi không tự tin trong C++ 11, nhưng tôi đoán trình biên dịch không thấy kết nối giữa bool (*)()const std::function<ReturnT()>&, ngay cả khi lần đầu tiên có thể được chuyển đổi hoàn toàn thành thứ hai cho ReturnT = bool.

+0

Làm thế nào một con trỏ hàm có thể được chuyển đổi thành một loại hàm? –

+0

Trên thực tế, bất kể chuyển đổi diễn ra như thế nào, định nghĩa của std :: function là: 'template hàm lớp ' trong đó 'R' được biết là' bool'… do đó ' ReturnT' nên được deducable cho 'foo', phải không? –

+0

@Karl, nhưng 'std :: function' có một hàm tạo dùng _any_ type, vì vậy' bool (*)() 'cũng có thể được chuyển thành' std :: function 'hoặc các kiểu khác - không có một, chuỗi chuyển đổi duy nhất có nghĩa là chỉ có một chuyên ngành 'std :: function' duy nhất có thể được suy ra –

13

Một con trỏ hàm của loại bool (*)() có thể được chuyển đổi thành std::function<bool()> nhưng không phải là cùng loại, do đó cần chuyển đổi. Trước khi trình biên dịch có thể kiểm tra xem chuyển đổi đó có thể cần phải suy ra ReturnTbool, nhưng để làm điều đó, cần phải biết rằng std::function<bool()> là một chuyển đổi có thể, điều này là không thể cho đến khi nó suy ra ReturnT ... xem sự cố?

Ngoài ra, hãy xem xét rằng bool(*)() cũng có thể được chuyển đổi thành std::function<void()> hoặc std::function<int()> ... cần được suy luận?

xem xét đơn giản hóa này:

template<typename T> 
    struct function 
    { 
    template<typename U> 
     function(U) { } 
    }; 

template<typename T> 
    void foo(function<T>) 
    { } 

int main() 
{ 
    foo(1); 
} 

Làm thế nào trình biên dịch có thể biết liệu bạn muốn tạo ra function<int> hoặc function<char> hoặc function<void> khi họ có thể tất cả được xây dựng dưới hình thức một int?

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