2013-07-05 35 views
6

Các mã sau trông hợp pháp nhưng không biên dịchqua chức năng như tham số mẫu phương pháp của lớp mẫu

void f() {} 

template<bool> 
struct call_any 
{ 
    template<typename F> 
    static void call(F f) {} 
}; 

template<bool B> 
void call_f() 
{ 
    call_any<true>::call<void (&)()>(f); // OK 
    call_any<false>::call<void (&)()>(f); // OK 
    call_any<B>::call<void()>(f);   // OK 
    call_any<B>::call<void (&)()>(f); // expected primary-expression before '>' 
} 

Tại sao có một lỗi và những gì nó có nghĩa gì?

Trả lời

10

Khi bạn đang xử lý các loại phụ thuộc vào thông số mẫu trong mẫu, trình biên dịch không biết loại thành viên nào thuộc loại đó. Trừ khi bạn chỉ định khác, nó giả định rằng các thành viên không phải là loại và không phải mẫu. Bởi vì điều này, nó đang cố gắng để điều trị < như là một nhà điều hành ít hơn, nhưng nó sẽ trở thành không thể phân tích các biểu thức theo cách đó vào thời điểm nó đạt đến >.

Để thoát khỏi những lỗi mà bạn nên sử dụng này để thay thế:

call_any<B>::template call<void (&)()>(f); 

này cho trình biên dịch một cách rõ ràng rằng call là một mẫu, vì vậy nó nên đối xử với các < là sự khởi đầu của các thông số mẫu và không phải là một toán tử nhỏ hơn thường lệ.

này nên sử dụng template cũng như:

call_any<B>::call<void()>(f); 

Lý do duy nhất bạn không thấy lỗi trên dòng này là có một cách để phân tích nó như một tổ chức phi mẫu:

(call_any<B>::call < void()) > (f); 

Mặc dù kỳ lạ, nó là hợp lệ về mặt pháp lý, do đó trình biên dịch vượt qua dòng đó và lỗi đầu tiên bạn thấy là lỗi bạn đề cập đến. Tuy nhiên, nếu không có từ khóa template, cuối cùng bạn sẽ gặp lỗi khi call_f thực sự được khởi tạo (có thể - có những cách kỳ lạ mà nó có thể hoạt động).

Hai ví dụ đầu tiên không sao nếu không sử dụng từ khóa template. Vì loại không phụ thuộc vào tham số mẫu, có thể xác định rằng call là mẫu trong khi call_f đang được phân tích cú pháp.

Bạn có thể hỏi: "Tại sao trình biên dịch không thể tìm ra nó là mẫu? Tôi đã định nghĩa nó như là một khuôn mẫu trong mã ngay phía trên!". Vấn đề là chuyên môn hóa. Bạn có thể chuyên template và làm điều gì đó hoàn toàn khác với những gì mẫu chính quy định cụ thể:

template<> 
struct call_any<false> 
{ 
    static const int call = 5; 
}; 

chuyên môn hóa này có thể xảy ra ngay cả sau khi call_f được xác định, vì vậy trình biên dịch không thể dựa vào những gì các mẫu chính cho call_any nói khi nó đang phân tích cú pháp call_f.

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