2012-02-07 35 views
9

Trong Andrei's talk on GoingNative 2012, ông nói về Mẫu biến thể và giải thích tại một điểm bằng ví dụ bên dưới cách mở rộng gói tham số hoạt động. Là khá mới đối với chủ đề này tôi thấy nó khá khó để làm theo như thế nào mỗi trường hợp hoạt động, ai có thể vui lòng giải thích cách mở rộng hoạt động trong mỗi cuộc gọi chức năng của gun?Variadic Templates mở rộng gói

template<class... Ts> void fun(Ts... vs) { 
    gun(A<Ts...>::hun(vs)...); 
    gun(A<Ts...>::hun(vs...)); 
    gun(A<Ts>::hun(vs)...); 
} 
+1

Bạn có thể muốn chỉ định 'Ts' là (ví dụ)' void *, int, char, std :: string' hoặc một cái gì đó, vì vậy các câu trả lời sắp xếp tốt hơn một chút. –

Trả lời

9

1.

gun(A<Ts...>::hun(vs)...) 
=> gun(A<T1, T2, …, Tn>::hun(vs)...) 
=> gun(A<T1, T2, …, Tn>::hun(v1), 
     A<T1, T2, …, Tn>::hun(v2), 
     …, 
     A<T1, T2, …, Tn>::hun(vm)) 

2.

gun(A<Ts...>::hun(vs...)) 
=> gun(A<T1, T2, …, Tn>::hun(vs...)) 
=> gun(A<T1, T2, …, Tn>::hun(v1, v2, …, vm)) 

này nên được rõ ràng.

3.

gun(A<Ts>::hun(vs)...) 
=> gun(A<T1>::hun(v1), A<T2>::hun(v2), …, A<Tn>::hun(vn)) 

(Trong trường hợp này chương trình sẽ không biên dịch nếu độ dài của Ts và vs khác nhau)


Các ... sẽ mở rộng một mô hình (trong đó bao gồm các gói thông số) preceeding it, có nghĩa là. Trong foo(Ts, Us, Vs)..., mỗi thành viên trong danh sách Ts, Us, Vs (được liệt kê trong bước khóa) sẽ được subsituted vào mô hình đó, và một danh sách dấu phẩy được hình thành:

foo(Ts, Us, Vs)... 
=> foo(T1, U1, V1), foo(T2, U2, V2), …, foo(Tn, Un, Vn) 

Và nếu có được lồng mở rộng, các mô hình trong cùng sẽ được mở rộng trước. Do đó, trong trường hợp 1, mẫu Ts trước tiên sẽ được mở rộng thành T1, T2, …, Tn. Và sau đó, mẫu phía trước bên ngoài ...A<T1, T2, …, Tn>::fun(vs) - lưu ý rằng Ts đã được mở rộng - vì vậy nó sẽ được mở rộng thành A<T1, T2, …, Tn>::fun(v1), <T1, T2, …, Tn>::fun(v2), …, <T1, T2, …, Tn>::fun(vm) bằng cách thay thế v1, v2, v.v. thành vs.

+0

Độ dài của 'Ts' và' vs' _can't_ khác nhau. Điều đó giống như nói rằng nó sẽ không biên dịch nếu '5' là nhiều hơn một' int'. –

+0

@MooingDuck: Độ dài chỉ giống nhau vì hàm được khai báo là 'mẫu void fun (Ts ... vs)'. Điều gì sẽ xảy ra nếu một tuyên bố khác 'mẫu void iun (Us ... vs)': p – kennytm

+0

@KennyTM: Gói tham số mẫu phải là đối số mẫu cuối cùng nếu không nó không thể được suy luận hoặc được chỉ định (14.1.11). –

4

Câu trả lời của KennyTM là hoàn hảo. Tôi cũng thích mẫu. Nhưng kể từ khi câu trả lời của ông là trừu tượng, tôi không cảm thấy như thêm bản demo cho câu trả lời của ông là điều đúng. Vì vậy, các bản trình diễn cho câu trả lời của anh ấy ở đây. Tôi cho rằng câu trả lời của anh ấy đúng, tôi không biết gì cả. (Nếu bạn upvote này, upvote của mình quá)

Rõ ràng đây là tất cả psudocode chỉ hiển thị trạng thái mở rộng.

void foo<void*,int,char,std::string>(nullptr, 32, '7', "BANANA") { 
    //gun(A<Ts...>::hun(vs)...); 
    gun(A<void*,int,char,std::string>::hun(nullptr) 
     ,A<void*,int,char,std::string>::hun(32) 
     ,A<void*,int,char,std::string>::hun('7') 
     ,A<void*,int,char,std::string>::hun("BANANA") 
     ); 
    //gun(A<Ts...>::hun(vs...)); 
    gun(A<void*,int,char,std::string>::hun(nullptr, 32, '7', "BANANA"); 
    //gun(A<Ts>::hun(vs)...); 
    gun(A<void*>::hun(nullptr) 
     ,A<int>::hun(32), 
     ,A<char>::hun('7'), 
     ,A<std::string>::hun("BANANA") 
     ); 
} 
+1

oh này! Tôi chỉ tìm thấy câu hỏi này xuất phát từ slide! –

+2

Sử dụng 'NULL' với mẫu variadic? Điều đó giống như sử dụng một chiếc Ferrari để kéo một trailer;) –

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