2016-06-06 14 views
8

tôi nhận thấy một cách tình cờ rằng mã này biên dịch và làm việc một cách chính xác:Tại sao decltype (lớp :: lớp :: lớp :: thành viên) có hiệu lực

struct M { int some_int; }; 
static_assert(std::is_same< 
        decltype(M::M::M::M::some_int) /* <- this */, 
        int>::value, "Types must be int"); 

Tại sao là đúng (decltype(M::M::M::M::some_int) <=> decltype(M::some_int)) này?

Những cấu trúc nào khác có thể sử dụng mẫu này với class::class::...::member?

Compiler: Microsoft (R) C/C++ Compiler Tối ưu hóa Version 19.00.23824.1 cho x86

+1

Oh boy..let flow upvotes cho một thứ rõ ràng là [duplicate] (http://stackoverflow.com/q/12135498). –

Trả lời

9

này hoạt động vì sự tiêm-class-name:

(N3337) [class]/2: Một lớp học có tên tuổi được đưa vào phạm vi trong đó nó được tuyên bố ngay sau khi class-name là đã xem. Tên lớp cũng được chèn vào phạm vi của chính lớp đó; điều này được gọi là tên lớp được tiêm. Để kiểm tra quyền truy cập, tên lớp được tiêm được coi như là tên thành viên công khai. [...]

Vì vậy, bạn có thể tùy tiện làm tổ này, và họ sẽ làm việc với các loại có nguồn gốc cũng như:

struct A { using type = int; }; 
struct B : public A {}; 

using foo = B::B::B::A::A::A::type; 

Lưu ý rằng trong trường hợp của A[::A]*::A, các tiêm-class-name có thể được coi là tên các nhà xây dựng thay vì:

[class.qual]/2: trong một tra cứu trong đó các nhà xây dựng là một kết quả tra cứu chấp nhận được và lồng nhau-tên-specifier đề cử một lớp C:

- nếu tên được chỉ định sau khi lồng nhau-tên-specifier, khi ngẩng đầu lên trong C, là tiêm-class-name của C (khoản 9), hoặc

- [...]

tên thay vì được xem là đặt tên cho hàm tạo của lớp C.

+2

* "Lưu ý rằng trong trường hợp của' A [:: A] * :: A', tên lớp được tiêm có thể được xem xét để đặt tên cho hàm tạo: "* Ib4 dấu gạch ngang theo dõi tự nhiên: Có, tiếng kêu có xu hướng để có được điều này sai. Xem ví dụ [this] (https://stackoverflow.com/questions/29681449/program-being-compiled-differently-in-3-major-c-compilers-which-one-is-right). –

10

này có giá trị trong mọi hoàn cảnh, không chỉ decltype. Một lớp có tên riêng của nó là tên lớp được tiêm . Vì vậy, trong một lớp học A::B::M, tên M được tiêm để tham chiếu đến lớp A::B::M. Điều này có nghĩa là bạn có thể sử dụng M::M::M::some_member để chỉ các thành viên của lớp đó, nếu bạn thực sự muốn.

[Live example]

Lưu ý rằng khi đề cập chỉ để tên lớp mình (ví dụ M::M::M), tình hình là hơi khác nhau. Nếu một tham chiếu như vậy xảy ra ở một nơi mà một tham chiếu đến một hàm cũng có thể có khả năng đúng, thì cú pháp đó được thực hiện để tham khảo hàm tạo. Tuy nhiên, trong các ngữ cảnh chỉ loại, ngay cả tham chiếu đó cũng hợp lệ. Ví dụ:

M::M::M m; // illegal, M::M interpreted as reference to constructor 

struct D : public M::M::M // legal, a function could not be references here, so M::M::M means M 
{}; 
Các vấn đề liên quan