2017-09-19 25 views
14
template <typename T> 
T go(T a, T *b){ T *t; return *t;} 

int main() { 
    const int x = 10; 
    go(x, &x); 
    return 0; 
} 

Cung cấp cho trình biên dịch báo lỗi:Template luận thất bại khấu trừ khi đi qua địa chỉ của kiểu const

error: no matching function for call to ‘go(const int&, const int*)’

Tại sao là đối số đầu tiên một loại tài liệu tham khảo const int& thay vì chỉ const int?

Để khắc phục lỗi biên dịch này, tôi đã vượt qua quá trình khấu trừ trình biên dịch bằng cách chỉ định loại đối số go<const int>(x, &x);, nhưng một lần nữa tại sao tôi cần thực hiện điều đó?

Trả lời

13

Đó là xung đột về khấu trừ loại. T được suy ra là int từ đối số đầu tiên và là const int từ đối số thứ hai. Do đó loại khấu trừ thất bại (và trình biên dịch trình bày một thông điệp mà có thể hoặc không thể làm cho nguyên nhân cơ bản rõ ràng).

Nếu bạn muốn làm cho công việc chức năng này mà không cần phải xác định các mẫu tranh luận một cách rõ ràng, bạn có thể làm cho nó để chỉ những luận cứ chức năng thứ hai ổ đĩa khấu trừ:

template <class T> 
struct NonDeduced { using type = T; } 

template <class T> 
T go(typename NonDeduced<T>::type a, T *b) { T *t; return *t; } 

Bằng cách đó, T sẽ chỉ có deducible từ đối số thứ hai, và tham số đầu tiên sẽ sử dụng suy ra T mà không sửa đổi.

+1

Cảm ơn, đó là thú vị, nhưng bạn có nghĩ rằng đó sẽ là một thực hành lập trình tốt xem xét lừa nó thực hiện trong nội bộ. –

+0

@SauravSahu Một khi bạn bắt đầu thực hiện những điều phi thường với các khuôn mẫu, bạn sẽ thấy có một 'NonDeduced' ở đâu đó là phải. Và một khi bạn có nó, bạn cũng có thể sử dụng nó. Cho dù đó là một ý tưởng hay trong trường hợp cụ thể này, hoặc liệu mọi thứ có thể được thực hiện khác nhau hay không, phụ thuộc phần lớn vào những gì 'go' thực sự làm trong trường hợp sử dụng thực sự của bạn. – Angew

6

a được khai báo để được thông qua bởi giá trị, sau đó trong template argument deduction:

c) otherwise, if A is a cv-qualified type, the top-level cv-qualifiers are ignored for deduction:

Điều đó có nghĩa, cho go(x, &x);, cho lập luận 1st x, các mẫu tham số T sẽ được suy luận như int, không const int. Đối với đối số thứ 2, T sẽ được suy ra là const int, vì b được khai báo là được chuyển bởi con trỏ (và các dấu kiểm định cv trên đối tượng đang được chỉ định được bảo lưu; điều tương tự cũng xảy ra khi tham chiếu). Sau đó khấu trừ không thành công.


BTW: clang cho thông điệp khá rõ ràng cho nó:

prog.cc:4:3: note: candidate template ignored: deduced conflicting types for parameter 'T' ('int' vs. 'const int')

+0

Tôi nghĩ OP đạt được cái nhìn sâu sắc mà thông điệp kêu vang đưa ra. Ông hỏi tại sao nó xảy ra – sehe

+0

@sehe Dường như OP tập trung vào phần * sai * của thông báo lỗi; Tôi muốn nói với OP rằng thông báo lỗi về xung đột khấu trừ mẫu sẽ giúp ích nhiều hơn. – songyuanyao

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