Tôi nghĩ rằng các định nghĩa của các mẫu là sai, trong cả hai trường hợp bạn đang kích hoạt đệ quy chính xác. Tôi dự kiến sẽ có trình biên dịch để chết với một số stackoverflow bên trong trình biên dịch nhưng một lỗi khác nhau được sản xuất ...
An thực hiện các are_same
mẫu variadic có thể là:
template <class... Args> // base (optional to declare the template)
struct are_same;
template <class A, class B, class... Args> // recursion
struct are_same<A,B,Args...> {
static const bool value = is_same<A,B>::value && are_same<A,Args...>::value;
};
template <class A, class B> // stop condition
struct are_same<A,B> {
static const bool value = is_same<A,B>::value;
};
Lưu ý rằng trong bước recursion
, một đối số bị xóa khỏi danh sách các đối số, do đó, vấn đề mới cần giải quyết là đã giảm phiên bản gốc. Loại lập trình meta mẫu này khá liên quan đến đệ quy, và các quy tắc tương tự được áp dụng, để có thể sử dụng đệ quy, bạn cần phải đảm bảo rằng mỗi bước đệ quy sẽ đưa bạn đến gần hơn với một giải pháp. Trong trường hợp cụ thể này, với danh sách N kiểu có khả năng tương tự, mỗi bước làm giảm vấn đề để tìm xem các kiểu N-1 có giống nhau hay không.
Bạn có thể sử dụng cách khác, như điều kiện dừng (thay thế một cựu) một phiên bản thoái hóa của vấn đề are_same
:
template <class A>
struct are_same<A> {
static const bool value = true;
};
Đó là thoái hóa theo nghĩa là nó không thực sự có ý nghĩa hỏi xem một loại duy nhất * are_same *, nhưng đối với các tác vụ lập trình meta khác nhau, nó có thể phù hợp.
Một thuật toán có khả năng hiệu quả hơn khác nhau (Tôi không chắc liệu trình biên dịch sẽ tránh instantiation của mẫu trong bước đệ quy ở trên) mà không phụ thuộc vào is_same
có thể là:
template <class... Args>
struct are_same;
template <class A, class... Args>
struct are_same<A,A,Args...> { // recursion
static const bool value = are_same<A,Args...>::value;
};
template <class A, class B, class... Args>
struct are_same<A,B,Args...> { // cut, A and B are not the same
static const bool value = false;
};
template <class A>
struct are_same<A> { // end of recursion
static const bool value = true;
};
Trong trường hợp này , trình biên dịch sẽ thích recursion
tới các bước cut
bất cứ khi nào hai loại giống nhau, vì vậy chúng tôi không cần kiểm tra is_same
nội bộ. Đồng thời, nếu trình biên dịch đi vào bước cut
, chúng tôi không cần xử lý phần còn lại của danh sách loại, vì chúng tôi đã biết câu trả lời.
thật là rực rỡ, đặc biệt là bước "ngắn mạch". Cảm ơn. – smallB
Rất hay, nhưng có một lỗi nhỏ trong đoạn mã 1. Nên là 'static const bool value = is_same :: value && are_same :: value;' –
@VJo: Chúng giống hệt nhau, một khi bạn đã chứng minh rằng 'A == B', định kỳ với' 'hoặc' 'không quan trọng chút nào, cũng không có lợi thế gì, bạn đang kích hoạt một phiên bản mới của mẫu và tại thời điểm này trình biên dịch sẽ giải quyết cho bất cứ kiểu' A' và 'B' nào (tức là' int ',' double' ...), cả hai đoạn mã đều giống nhau. –