2012-04-25 8 views
5

Tôi không thể hiểu tại sao đoạn mã sau biên dịch tốt:C++ Chức năng Template instantiaion với các thông số ngầm

#include <iostream>                 

void bar(int x) {                 
    std::cout << "int " << x << std::endl;            
}                     

void bar(double x) {                 
    std::cout << "double " << x << std::endl;           
}                     

template <typename A, typename B> // Note the order of A and B.            
void foo(B x) {                  
    bar((A)x);                   
}                     

int main() {                   
    int x = 1;                   
    double y = 2;                  

    foo<int>(x);  // Compiles OK.                
    foo<double>(y);  // Compiles OK.            

    return 0;                   
} 

Nhưng nếu tôi chuyển đổi thứ tự của AB như dưới đây, sau đó nó sẽ không biên dịch:

#include <iostream>                 

void bar(int x) {                 
    std::cout << "int " << x << std::endl;            
}                     

void bar(double x) {                 
    std::cout << "double " << x << std::endl;           
}                     

template <typename B, typename A> // Order of A and B are switched. 
void foo(B x) {                  
    bar((A)x);                   
}                     

int main() {                   
    int x = 1;                   
    double y = 2;                  

    foo<int>(x);  // error: no matching function for call to ‘foo(int&)’ 
    foo<double>(y);  // error: no matching function for call to ‘foo(double&)’                

    return 0;                   
}  

EDIT: Giải thích đặc biệt được hoan nghênh, nhưng sẽ tốt hơn nếu ai đó có thể chỉ ra chính xác thông số. nói. Cảm ơn!

+1

Trình biên dịch có thể suy ra loại B trong ví dụ đầu tiên của bạn từ tham số được truyền cho hàm tạo foo (thuộc loại B). Trong ví dụ thứ hai, không có suy luận như vậy có thể được thực hiện, bởi vì tham số mẫu được cung cấp là B, và do đó là tham số hàm tạo. Loại A không có trong chứng cứ. – Stabledog

Trả lời

7

Trong cái đầu tiên, trình biên dịch biết rằng Aint vì bạn đặc biệt nói với nó như vậy với foo<int>, và nó biết rằng B cũng là int vì các tham số mà bạn vượt qua nó. Vì vậy, cả hai số AB đều được biết hoặc có thể được suy luận (bạn có thể nói: Ađược cung cấp, Bngụ ý).

Tuy nhiên, trong trường hợp thứ hai, kể từ B đến trước và A không xuất hiện trong danh sách tham số, trình biên dịch không thể cho biết số A là gì và cung cấp cho bạn lỗi. Bạn đang nói rõ điều gì là B là với foo<int>, và sau đó thông số bạn vượt qua cũng là B, tại cuộc gọi, là int đồng ý với định nghĩa rõ ràng trước đây của bạn là B, nhưng không đề cập đến là A, hoặc rõ ràng, do đó trình biên dịch phải dừng và lỗi.

Bạn không thực sự cần tiêu chuẩn cho điều này, đó chỉ là cảm giác thông thường. Những gì trên trái đất sẽ A được trong thứ hai?

Cảm ơn bạn đã đặt câu hỏi này, vì tôi không nhận ra bạn có thể chỉ định rõ ràng một số tham số và chỉ định rõ ràng những người khác trong danh sách tham số trước đó.

+0

Vì vậy, điều này trở thành một câu hỏi về những gì spec. nói về cách 'A' và' B' được xác định. Trình biên dịch có thể đã xác định 'B' vì đối số đầu vào đầu tiên, sau đó tìm ra' A' từ 'foo '. Sau đó, cả hai tham số mẫu được xác định ngay cả trong trường hợp thứ hai. – kirakun

+1

@Kirakun không thực sự. 'A' và' B' chỉ có thể được xác định nếu bạn chỉ định một loại trong '<>', hoặc tất cả những cái không được chỉ định trong '<>' đều nằm trong danh sách tham số, do đó trình biên dịch có thể suy ra nhập từ cuộc gọi. Trong câu lệnh thứ hai, 'A' không được chỉ rõ một cách rõ ràng trong' <> 'cũng như không nằm trong danh sách tham số, vì vậy không thể biết được. –

+1

@Kirakun chỉ vì bạn đặt một trong danh sách tham số không có nghĩa là nó bị bỏ qua khi bạn bắt đầu đặt mọi thứ giữa '<>'. Chúng vẫn theo thứ tự trong danh sách 'template ', vì vậy 'B' là đầu tiên, và sau đó' A' giây, luôn luôn, bất chấp các đối số mà hàm nhận được. –