2010-03-05 34 views
19

Trong đoạn mã sauluận Magic trong chức năng mẫu

#include<iostream> 

template<typename T,size_t N> 
void cal_size(T (&a)[N]) 
{ 
    std::cout<<"size of array is: "<<N<<std::endl; 
} 

int main() 
{ 
    int a[]={1,2,3,4,5,6}; 
    int b[]={1}; 

    cal_size(a); 
    cal_size(b); 
} 

Đúng như dự đoán kích thước của cả hai mảng được in. Nhưng N tự động được khởi tạo như thế nào với giá trị đúng của mảng-kích thước (các mảng đang được truyền theo tham chiếu)? Mã trên hoạt động như thế nào?

+2

Xem http: // stackoverflow.com/questions/437150/can-someone-explain-this-template-code-đó-cung cấp cho tôi-the-size-of-an-mảng (dupe?) –

+3

"mẫu đối số khấu trừ" là những gì tôi đang tìm kiếm. Cảm ơn Andrey :) –

Trả lời

31

N không được "khởi tạo" cho bất kỳ thứ gì. Nó không phải là một biến. Nó không phải là một vật thể. N là hằng số biên dịch. N chỉ tồn tại trong quá trình biên dịch. Giá trị của N cũng như số thực tế T được xác định bởi quá trình được gọi là khấu trừ đối số mẫu. Cả hai TN được suy ra từ loại đối số thực tế mà bạn chuyển đến chức năng mẫu của bạn.

Trong lần gọi đầu tiên, loại đối số là int[6], do đó trình biên dịch suy ra rằng T == intN == 6, tạo ra một hàm riêng biệt cho điều đó và gọi nó. Hãy đặt tên cho nó cal_size_int_6

void cal_size_int_6(int (&a)[6]) 
{ 
    std::cout << "size of array is: " << 6 << std::endl; 
} 

Lưu ý rằng không có T và không N trong chức năng này nữa. Cả hai đều được thay thế bằng giá trị suy luận thực tế của chúng tại thời gian biên dịch.

Trong lần gọi đầu tiên, loại đối số là int[1], do đó trình biên dịch suy ra rằng T == intN == 1, tạo ra một chức năng riêng biệt cho điều đó và gọi nó. Hãy đặt tên cho nó là cal_size_int_1

void cal_size_int_1(int (&a)[1]) 
{ 
    std::cout << "size of array is: " << 1 << std::endl; 
} 

Điều tương tự ở đây.

bạn main về cơ bản chuyển thành

int main() 
{ 
    int a[]={1,2,3,4,5,6}; 
    int b[]={1}; 

    cal_size_int_6(a); 
    cal_size_int_1(b); 
} 

Nói cách khác, mẫu cal_size bạn mang đến cho sinh hai chức năng khác nhau (cái gọi là chuyên ngành của mẫu ban đầu), đều có giá trị khác nhau của N (và T) được mã hóa cứng vào cơ thể. Đó là cách các mẫu làm việc trong C++.

+3

Trong thực tế, comeau chấp nhận điều này: 'template void f (int (&)[S]); int main() {int a [UCHAR_MAX + 1]; f (a);}'. , tôi thậm chí không chắc chắn những gì tiêu chuẩn nói về đoạn mã này (có vẻ như để nói cuộc gọi thành công, nhưng không xác định giá trị 'S' có trong cơ thể chức năng) .Trong mọi trường hợp, comeau cho' S' loại "unsigned char", nhưng cung cấp cho nó giá trị thực (ngoài phạm vi của nó) trong phần thân hàm. –

1

khi bạn khai báo int [] = {1,2,3}, nó giống như (hoặc sẽ được viết lại thành) int [3] = {1,2,3} kể từ khi chức năng khuôn mẫu được nhận đối số dưới dạng T a [N], thì N sẽ có giá trị là 3.

8

Nó hoạt động vì loại a là "mảng chiều dài 6 của int" và loại b là "mảng có độ dài 1 int ". Trình biên dịch biết điều này, vì vậy nó có thể gọi chức năng chính xác. Cụ thể, cuộc gọi đầu tiên gọi phiên bản mẫu cal_size<6>() và cuộc gọi thứ hai gọi cal_size<1>(), vì đó là cuộc gọi mẫu duy nhất khớp với đối số tương ứng của chúng.

Nếu bạn cố gắng gọi một thể hiện mẫu rõ ràng, nó sẽ chỉ hoạt động nếu bạn có kích thước phù hợp, nếu không các đối số sẽ không khớp. Hãy xem xét những điều sau:

cal_size(a); // ok, compiler figures out implicitly that N=6 
cal_size<int, 6>(a); // also ok, same result as above 
cal_size<int, 5>(a); // ERROR: a is not of type "array of length 5 of int" 
Các vấn đề liên quan