2013-07-23 25 views
19

Tôi đã cố gắng để biên dịch một dự án (mà là tốt bằng cách sử dụng gcc/g + +) với tiếng kêu và biên dịch bị mắc kẹt trên một lời gọi mẫu. Tôi đã cố tạo một đoạn mã tương tự đơn giản nhất có cùng thông báo lỗi. Ở đây là:Clang "không thể suy luận đối số mẫu" trong khi gcc/g ++ có thể. Cái nào đúng?

#include <vector> 
#include <utility> 
#include <iostream> 

using namespace std; 

int A(double in) 
{ 
    return 1; 
} 

int A(int in) 
{ 
    return 1; 
} 


template<class M, class T> 
M test(T input, M (fun) (T)) 
{ 
    return fun(input); 
} 



int main(int argc, const char *argv[]) 
{ 
    cout << test((int) 1, A) << test((double) 1.2, A) << endl; 
    return 0; 
} 

Các lỗi từ kêu vang (xuất hiện hai lần tất nhiên):

error: no matching function for call to 'test' 
candidate template ignored: couldn't infer template argument 'M' 

Gcc không phàn nàn. Xin lưu ý M là kiểu trả về và luôn là "int".

Có ai đó biết điều gì đúng và lý do không?

Cảm ơn

+0

bạn có thử dùng (..., & A) thay thế không? –

+0

Stefano: Tôi đã thử, nó không có sự khác biệt. – Max

+0

Và nó không nên. Không cần sử dụng toán tử địa chỉ trên tên hàm để lấy con trỏ hàm. (Và tương tự, không cần phải rõ ràng dereference một con trỏ chức năng với '*' để gọi nó.) Mặc dù bạn có thể nếu bạn thực sự muốn, nhưng nó làm cho không có sự khác biệt. – BoBTFish

Trả lời

2

Câu trả lời trước của tôi (bây giờ đã bị xóa) không đúng. Clang sai rồi.

Trình biên dịch có thể suy ra loại M vì đối số hàm là M(fun)(T). Lưu ý rằng không có M trong danh sách đối số con trỏ hàm, vì vậy đây tương ứng với T() (C++ 11)/T(*)() (C++ 93) trong 14.8.2.5:

nơi (T) đại diện cho một tham số -type-list trong đó ít nhất một loại thông số chứa T() đại diện cho thông số kiểu danh sách trong đó không có loại thông số nào chứa T.

+1

+1 bởi vì tôi tin rằng bạn chính xác và đây là lỗi nghiêm trọng. –

+0

Không nên là 'loại (T)' để tuân thủ tiêu chuẩn? – maverik

+0

@maverik - Không. Hoặc là 'T()' hoặc 'T (T)' có thể được sử dụng để phân tích kiểu mẫu 'T'. Lưu ý rằng '()' không có nghĩa là một hàm không có đối số. Nó đơn giản có nghĩa là không có đối số hàm nào chứa 'T'. –

8

g ++ là sai. Từ C++ 11 [temp.deduct.type] p5:

Các bối cảnh phi suy luận là: [...] - Một số chức năng mà khấu trừ đối số không thể được thực hiện bởi vì đối số chức năng liên quan là [...] một tập hợp các hàm bị quá tải và [...] nhiều hơn một hàm phù hợp với loại tham số chức năng

Xác định này được thực hiện mà không quan tâm đến các tham số mẫu có thể đã được suy ra ở nơi khác, vì vậy thực tế là T phải suy ra là int không có liên quan ở đây. Điều này làm cho toàn bộ tham số M (fun)(T) một ngữ cảnh không được suy luận. Do đó, không thể suy ra M, như Clang tuyên bố.

g ++ xuất hiện không chính xác khi sử dụng tham số 'T = int' từ thông số hàm đầu tiên khi xác định xem tham số thứ hai có phải là ngữ cảnh không được suy luận hay không. Đảo ngược thứ tự của các tham số chức năng cũng làm cho g + + từ chối mã:

int A(double); 
int A(int); 
template<class M, class T> 
M test(M (fun) (T), T input) { 
    return fun(input); 
} 
int main(int argc, const char *argv[]) { 
    test(A, 1); 
    test(A, 1.2); 
} 
+0

Điều này có vẻ chính xác. (Một điều làm tôi bối rối một lúc: "tham số chức năng" là một ngữ cảnh không suy luận là 'M (vui) (T)', không phải là tham số cho 'A'. Mặc dù câu trả lời đã giải thích điều đó.) – aschepler

+0

Loại điều này là lý do tại sao tôi thích sử dụng functors bất cứ nơi nào có thể thay vì con trỏ hàm. – SirGuy

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