2010-04-25 24 views
5

Về mã bên dưới, trình biên dịch chọn chức năng mẫu nào để gọi? Nếu chức năng const T & bị bỏ qua, chức năng T & luôn được gọi. Nếu chức năng T & bị bỏ qua, hàm const T & luôn được gọi. Nếu cả hai được bao gồm, kết quả như sau.Làm thế nào để biên dịch chọn chức năng mẫu để gọi?

#include <iostream> 
#include <typeinfo> 

template <typename T> 
void function(const T &t) 
{ 
    std::cout << "function<" << typeid(T).name() << ">(const T&) called with t = " << t << std::endl; 
} 

template <typename T> 
void function(T &t) 
{ 
    std::cout << "function<" << typeid(T).name() << ">(T&) called with t = " << t << std::endl; 
} 

int main() 
{ 
    int i1 = 57; 
    const int i2 = -6; 

    int *pi1 = &i1; 
    int *const pi3 = &i1; 
    const int *pi2 = &i2; 
    const int *const pi4 = &i2; 

    function(pi1); ///just a normal pointer -> T& 
    function(pi2); ///cannot change what we point to -> T& 
    function(pi3); ///cannot change where we point -> const T& 
    function(pi4); ///cannot change everything -> const T& 

    return 0; 
} 

/* g++ output: 
function<Pi>(T&) called with t = 0x22cd24 
function<PKi>(T&) called with t = 0x22cd20 
function<Pi>(const T&) called with t = 0x22cd24 
function<PKi>(const T&) called with t = 0x22cd20 
*/ 

/* bcc32 output: 
function<int *>(T&) called with t = 0012FF50 
function<const int *>(T&) called with t = 0012FF4C 
function<int *>(const T&) called with t = 0012FF50 
function<const int *>(const T&) called with t = 0012FF4C 
*/ 

/* cl output: 
function<int *>(T&) called with t = 0012FF34 
function<int const *>(T&) called with t = 0012FF28 
function<int *>(const T&) called with t = 0012FF34 
function<int const *>(const T&) called with t = 0012FF28 
*/ 
+0

Một mẹo nhỏ, khi bạn tình cờ được sử dụng g ++. '__PRETTY_FUNCTION__' cung cấp một chuỗi được định dạng tốt mô tả chức năng của bạn, bao gồm các kiểu tham số mẫu [" int * "thay vì" Pi "]. Tôi thấy điều này vô giá khi học cách các mẫu làm việc, vì hành vi mặc định cho 'typeid (T) .name()' dưới g ++ khá khó hiểu. Tôi tin rằng '__FUNCSIG__' cung cấp chức năng tương tự theo VS, nhưng tôi không có quyền truy cập vào nó để xác minh. –

Trả lời

3

Here là bản tóm tắt ngắn gọn về quy trình trình biên dịch trải qua. Nó không bao gồm mọi thứ, nhưng nó giúp bạn bắt đầu.

Trong trường hợp này, quyết định được thực hiện giống như chức năng không có khuôn mẫu. Với void f(int&)void f(const int&), giá trị đầu tiên sẽ được chọn cho ints thông thường và giá trị thứ hai cho const ints. Các tham số đơn giản khớp với đầu vào tốt hơn theo cách này: nếu bạn cung cấp một biến mà bạn có thể sửa đổi, nó gọi hàm có thể sửa đổi chúng, nếu bạn cung cấp một biến mà bạn không thể sửa đổi, nó gọi hàm không thể sửa đổi chúng.

Trong mã mẫu của bạn, pi2, được khai báo là const int *, là một con trỏ không liên tục đến dữ liệu cố định. Vì vậy, trong chức năng của bạn, bạn có thể thay đổi t, nhưng không thay đổi *t. Ngược lại, pi3 là một con trỏ không đổi đối với dữ liệu không liên tục. Vì vậy, bạn có thể thay đổi *t nhưng không thay đổi t.

Nếu bạn đã thay đổi mã của bạn một chút:

function(*pi1); 
function(*p12); 
function(*pi3); 
function(*pi4); 

Trong trường hợp này, người đầu tiên và thứ ba sẽ giải quyết cả hai phiên bản T&, vì *pi1*pi3 đều là kiểu int& và do đó có thể được sửa đổi. *pi2*pi4 đều là const int&, vì vậy, chúng giải quyết cho quá tải const T&.

0

đó là về việc liệu biến có phải là hằng số không: biến số đầu tiên không phải là không đổi. điểm thứ hai trỏ đến thứ gì đó liên tục, nhưng chúng ta có thể thay đổi nơi nó trỏ tới, cả ba và thứ tư đều có con trỏ không đổi, có nghĩa là biến là const, chúng ta không thể thay đổi bất cứ nơi nào nó trỏ đến.

typedef const int Cint; 
Cint * int1; 

rõ ràng là con trỏ tới int cố định.

typedef int * Pint 
const Pint int2 

con trỏ rõ ràng liên tục để không liên tục int

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