2016-10-27 15 views
6

Nó thường là khá trực quan những gì các mẫu chính của một chuyên môn mẫu chức năng là, tuy nhiên, tôi đang tìm kiếm các quy tắc chính thức để hiểu được những tình huống đáng ngạc nhiên hơn. Ví dụ:Làm thế nào để xác định mẫu chính của một chuyên môn chức năng?

template <typename T, typename U> 
void f(T, U) {}  // (1) 

template <typename T> 
void f(T, T) {}  // (2) 

template <> 
void f(int, int) {} // (3); specializes (2), not (1); why? 

Về mặt lý thuyết, (3) cũng có thể là chuyên môn hóa (1), nhưng như các thử nghiệm cho thấy không.

+0

Bạn có thể thêm chi tiết khác vào thử nghiệm của mình không? – Bertrand

+0

Chính xác thì ý của bạn là gì bởi "mẫu chính của chuyên môn khuôn mẫu hàm" trong thuật ngữ trình biên dịch? Bạn có một liên kết đến một định nghĩa chính thức hay chỉ là một thuật ngữ mà bạn đã đề xuất cho mục đích của câu hỏi này? Tôi không thể xoay bộ não của tôi để xem "chuyên môn hóa mẫu" trong một ánh sáng tương tự như "là một/thừa kế" quan hệ - mỗi chuyên môn thực sự là một mẫu trên rất riêng của nó, chỉ cụ thể hơn "chung" mẫu có cùng tên . (kết quả cuối cùng của quá trình biên dịch sẽ hiển thị nhiều hàm được định nghĩa, vì vậy đây là thứ chỉ có nghĩa trong quá trình biên dịch) –

+0

@Bertrand Thử nghiệm rất đơn giản: Cho phép mỗi hàm in số của nó và thêm 'int main() {f (0 , 0); } '. Chương trình đầu ra '(3)' và do đó (3) là một chuyên môn của (2), không phải của (1). – user1494080

Trả lời

8

Hãy tập trung vào việc khai báo các mẫu chung (1) và (2). Đây là hai mẫu riêng biệt, ví dụ: (2) không phải là chuyên môn hóa (1). Ok, bây giờ khi chúng tôi viết chuyên môn:

template <> 
void foo(int, int) {} 

Khi suy ra mẫu nào để chuyên, trình biên dịch sẽ xác định hai ứng cử viên. Sau đó, nó phải chọn là phù hợp nhất. Quy trình cho lựa chọn như vậy được gọi là "partial ordering of function templates". quote chọn:

Khi cùng chức năng mẫu chuyên môn phù hợp với nhiều hơn một chức năng mẫu quá tải (điều này thường dẫn đến từ khấu trừ mẫu đối số), đặt hàng một phần của mẫu chức năng quá tải được thực hiện để chọn phù hợp nhất.

Hãy gọi S tập hợp mẫu phù hợp. Sau đó, đối với mỗi cặp (f1, f2) trong S, trình biên dịch sẽ chuyển đổi f1 bằng cách áp dụng các loại giả (giá trị hồi đáp) vào các thông số loại (không phải loại). Sau đó, nó cố gắng đối sánh nó với f2. Sau đó, thực hiện thủ tục tương tự bằng cách chuyển đổi f2 và cố gắng đối sánh nó với f1. Cuối cùng, sau khi đi qua từng cặp, trình biên dịch có thể xác định ứng cử viên mẫu nào là chuyên biệt nhất. Nếu nó không làm như vậy trình biên dịch không thành công.

Trong trường hợp của chúng tôi, chúng tôi đã có hai mẫu phù hợp vì vậy chúng tôi áp dụng các thủ tục mô tả ở trên:

  • phẩm cải biên (1) áp dụng cho (2): Giả sử foo với T = T1 và U = T2. Nó cố gắng để phù hợp với (2): khấu trừ không
  • Biến đổi (2) áp dụng cho (1): foo (T1, T1), khi áp dụng cho (1), nó giải quyết như T = T1 và U = T1.

Từ quy trình này, trình biên dịch suy luận rằng (2) chuyên biệt hơn (1) và chuyên môn của bạn đi cho (2). Quá trình tương tự được áp dụng trong quá trình phân giải quá tải khi trình biên dịch tập trung vào một cuộc gọi cụ thể.

Một ví dụ minh họa tất cả các thủ tục này là như sau (lấy từ @ bình luận Yakk của):

template <typename T, typename U> 
void f(T, U) { std::cout << "f(1)\n"; }  // f(1) 

template <typename T> 
void f(T, T) { std::cout << "f(2)\n"; }  // f(2) 

template <> 
void f(int, int) { std::cout << "f(3)\n"; } // f(3); specializes f(2), not f(1); why? 

// Now the same specialization but without any template overload... 
template <typename T, typename U> 
void g(T, U) { std::cout << "g(1)\n"; }  // g(1) 

template <> 
void g(int, int) { std::cout << "g(3)\n"; } // g(3); No ambiguity, specializes g(1) 

Tiếp theo, chúng ta hãy thực hiện một vài cuộc gọi:

f(1, 1); // Prints f(3) 
f<int>(1, 1); // Prints f(3) 
f<int, int>(1, 1); // Prints f(1) 
g(1, 1); // Prints g(3) 

g<int, int>(1, 1); // Prints g(3) 

Tất cả điều này có thể được nhìn thấy trong hành động here - copied from @Yakk's comment.

+0

Vâng, tôi thậm chí còn biết tại sao 'foo (1, 1)' được so khớp với (2): vì các quy tắc đặt hàng một phần của các mẫu chức năng quá tải. Nhưng có, đó thực sự không phải là câu hỏi của tôi. – user1494080

+0

@Yakk Đã chỉnh sửa câu trả lời của tôi để có thêm điểm. – Rerito

+0

@ user1494080 Sau khi đọc thêm về nó, có vẻ như cùng một kỹ thuật đặt hàng một phần được sử dụng để suy ra mẫu để chuyên – Rerito

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