6

Mã nguồn sau đây được mang đến từ: Understanding partial specialization of inherited nested class templatesChuyên ngành kế thừa lồng lớp mẫu

#include <type_traits> 
struct Base 
{ 
    template<class U, class _ = void> struct Inner: std::true_type {}; 
    template<class _> struct Inner<char, _>: std::false_type {}; 
}; 
struct Derived : Base 
{ 
}; 

template<class _> struct Derived::Inner<int, _>: std::false_type {}; 

Tôi đã có một vấn đề về chuyên lớp được thừa kế, vì vậy tôi googled, và tìm hiểu các câu hỏi trên. Mã nguồn trong câu hỏi ở trên được biên dịch w/o bất kỳ vấn đề nào trong gcc/clang, nhưng msvc từ chối biên dịch nó, phát hành C2427 (xem https://msdn.microsoft.com/en-us/library/10het5hx.aspx).

Tình huống ở trên (chuyên lớp lồng nhau của một lớp không phải mẫu) hoàn toàn khác với tình huống được mô tả trong https://msdn.microsoft.com/en-us/library/10het5hx.aspx (xác định lớp không phải mẫu lồng nhau của một lớp mẫu), tôi nghĩ vậy.

Giá trị nào của msvc so với gcc/clang là sai? Hoặc chỉ là tiêu chuẩn là không rõ ràng để xác định hành vi này?

Tôi hy vọng msvc là sai ...

Trả lời

2

Clang và GCC là sai, và MSVC và EDG là quyền từ chối rằng định nghĩa chuyên môn hóa một phần.

Chuyên môn từng phần là bản thân mẫu và định nghĩa mẫu lớp được xây dựng theo cú pháp theo định nghĩa lớp (theo ngữ pháp, số lớp-specifier). Trong định nghĩa như vậy, Derived::Inner<int, _>tên lớp học, với Derived:: là một tên lồng nhau-specifier.

[9p11] trong tiêu chuẩn nói:

Nếu một đẳng cấp đầu tên chứa một lồng nhau-tên-specifier, các đẳng cấp specifier sẽ đề cập đến một lớp học mà trước đây đã được khai báo là trực tiếp trong lớp hoặc không gian tên mà theo đó tên lồng nhau-name-specifier tham chiếu hoặc trong phần tử của bộ không gian tên nội tuyến (7.3.1) của không gian tên đó (không phải chỉ thừa kế o r được giới thiệu bởi một số sử dụng khai báo) và lớp-specifier sẽ xuất hiện trong một không gian tên kèm theo tuyên bố trước đó. [...]

Vì vậy, bạn phải sử dụng Base::Inner<int, _>.


Như đã đề cập trong các ý kiến, báo giá trên áp dụng cho lớp mẫu định nghĩa chuyên môn hóa rõ ràng cũng như (sản xuất ngữ pháp của họ cũng kết thúc bằng đẳng cấp đầu tên).


Điều sau đây không áp dụng trực tiếp cho ví dụ của bạn, nhưng tôi thấy nó đáng nhắc đến.

Lưu ý rằng các báo trên đề cập đến lớp mẫu (hoặc chuyên môn hóa rõ ràng) định nghĩa, không khai báo như

template<class _> struct Derived::Inner<int, _>; 

Cú pháp, struct Derived::Inner<int, _> trong đó là một xây dựng-type-specifier, mà đoạn ở trên không áp dụng. Vì vậy, các từ ngữ tiêu chuẩn kỹ thuật cho phép khai báo như vậy.

này dường như không có một sự giám sát: các từ ngữ trên đã được giới thiệu bởi các nghị quyết của DR284, trong đó bao gồm những nhận xét:

Những tình cảm được rằng điều này nên được yêu cầu về định nghĩa lớp, nhưng không phải trên các thông số kiểu công phu nói chung (là các tài liệu tham khảo , không phải khai báo). [...]

Độ phân giải được đề xuất bao gồm được xây dựng theo kiểu-specifier, nhưng chúng đã bị xóa khỏi từ ngữ cuối cùng.

Tuy nhiên, cả MSVC lẫn EDG đều không chấp nhận các khai báo đó (và thẳng thắn tôi sẽ thấy nó khó hiểu nếu chúng đã làm). Nhận xét trong DR dường như chỉ ra rằng mục đích là chỉ cho phép được xây dựng theo kiểu-specifier cũng không phải là khai báo, nhưng có vẻ như điều này không được phản ánh trong từ ngữ (một lỗi Chuẩn).

+0

Đó là quá xấu ... Sẽ rất tuyệt nếu tôi có thể chuyên mẫu lớp lồng nhau bằng cách sử dụng tên lớp dẫn xuất ... Dù sao, cảm ơn bạn đã trả lời rất nhiều thông tin! Nhân tiện, [9p11] có áp dụng cho chuyên môn hóa rõ ràng không? Có vẻ như msvc vẫn từ chối khi tôi xóa thông số giả trong ví dụ. –

+0

@JunekeyJeon Vâng, nó có, theo như tôi có thể nói. – bogdan

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