2012-05-03 19 views
11

Gần đây tôi đã bắt đầu sử dụng C++ 11 và tôi đã đọc trong hướng dẫn về các mẫu variadic. Tôi đã hiểu rằng chúng ta có thể xác định một mẫu variadic như thế nàyXử lý các mẫu có định dạng vd trong C++ 11

// example class that uses variadic template 
template<typename ...Args> struct mtuple; 

Nhưng làm thế nào tôi có thể xử lý các đối số mẫu của lớp mtuple (ví dụ như thế nào sẽ nhìn get<int>(mtuple_obj) như thế nào?)?

+4

Ma thuật mẫu biến thể thực sự huyền diệu, bạn phải thử nghiệm nó, cũng như xem nhiều mẫu mã khác nhau để xem cái gì và tại sao lại xảy ra ở đó. [Đây là nỗ lực của tôi để viết lớp Tuple riêng (mặc dù không nhìn vào 'Tie()'; D)] (https://github.com/griwes/LibRose/blob/master/librosec%2B%2B/tuple .hxx), là một trong những mẫu mã như vậy, cũng có rất nhiều ở đây, trên SO - duyệt qua [tag: variadic-templates] và cố gắng hiểu chúng. – Griwes

+1

vài câu hỏi thú vị có liên quan: http://stackoverflow.com/a/7868427/170521 và http://stackoverflow.com/q/7870498/170521 – lurscher

Trả lời

4

Hình thức get<1>(t) sẽ phụ thuộc vào việc triển khai mtuple. Một triển khai điển hình được kế thừa từ một loại chứa mỗi đối số, do đó, mtuple<A,B,C> được kế thừa từ TupleHead<A> (có thành viên loại A) và cũng được kế thừa từ TupleTail<B,C>. TupleTail<B,C> được kế thừa từ TupleHead<B> (có thành viên loại B) và TupleTail<C>. TupleTail<C> thừa hưởng từ TupleHead<C>

Bây giờ, nếu bạn cung cấp cho mỗi lớp cơ sở một số nguyên quá (trong đó có một thành viên của loại C.):

mtuple<A,B,C> thừa hưởng từ TupleHead<0,A>TupleTail<1,B,C>

TupleTail<1,B,C> thừa hưởng từ TupleHead<1,B>TupleTail<2,C>

TupleTail<2,C> được thừa kế từ TupleHead<2,C>

Bây giờ việc viết get<1> là tương đối đơn giản, vì mtuple có một lớp cơ sở duy nhất kiểu TupleHead<1,B> có thể thu được bằng cách trả về, sau đó trả về thành viên B của lớp cơ sở đó.

[Edit: get<1>(m) cần phải biết loại B tương ứng với các yếu tố tuple với chỉ số 1, cho rằng bạn sử dụng một cái gì đó giống như std::tuple_element mà cũng dựa trên hệ thống phân cấp thừa kế đệ quy mô tả ở trên và sử dụng chuyên môn hóa một phần để có được những cơ sở TupleHead<1,T> với chỉ số 1, sau đó xác định tham số T trong chuyên môn từng phần đó, cung cấp B trong ví dụ của tôi.]

Nhiều kỹ thuật được sử dụng với các mẫu variadic là các kỹ thuật lập trình hàm, chẳng hạn như hoạt động trên phần tử đầu tiên của mẫu gói tham số, sau đó đệ quy làm điều tương tự trên phần còn lại của gói, cho đến khi bạn đã pr trao cho tất cả các yếu tố.Không có nhiều thứ bạn có thể làm với gói tham số mẫu trực tiếp ngoại trừ đếm kích thước của nó (với sizeof...) hoặc tạo một mẫu khác với nó, vì vậy cách tiếp cận thông thường là tạo mẫu khác tách gói Args thành ArgHead, ArgsTail... và xử lý đầu , sau đó đệ quy làm tương tự với ArgsTail

4

Không có cơ chế đơn giản nào để lặp qua các giá trị của mẫu có định dạng variadic. Nhưng điều này có thể được thực hiện đệ quy. Dưới đây là một ví dụ:

template<typename T, typename... Args> 
void print_values(const char *s, T value, Args... args) 
{ 
    while (*s) { 
     if (*s == '%' && *(++s) != '%') { 
      std::cout << value; 
      ++s; 
      print_values(s, args...); 
      return; 
     } 
     cout << *(s++); 
    } 
} 

Vì vậy, nếu tôi gọi print_values("%d %d %d", 1, 2, 3) tôi nhận được cây đệ quy này:

print_values("%d %d %d", 1, 2, 3) // value -> 1, args... -> 2,3 
print_values("%d %d", 2, 3) // value -> 2, args... -> 3 
print_values("%d", 3) // value -> 3, args... -> NULL 
print_values("") // value -> NULL, args... -> NULL 

tôi đệ quy gọi print_values() ngay cả khi * s == 0 để phát hiện thêm đối số

Nguồn: http://en.wikipedia.org/wiki/Variadic_templates

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