2009-07-01 32 views
9

Có ai biết tại sao việc sử dụng khai báo dường như không hoạt động để nhập tên kiểu từ các lớp cơ sở phụ thuộc không? Chúng hoạt động cho các biến thành viên và các hàm, nhưng ít nhất trong GCC 4.3, chúng dường như bị bỏ qua đối với các kiểu.Truy cập các loại từ các lớp cơ sở phụ thuộc

template <class T> 
struct Base 
{ 
    typedef T value_type; 
}; 

template <class T> 
struct Derived : Base<T> 
{ 
    // Version 1: error on conforming compilers 
    value_type get(); 

    // Version 2: OK, but unwieldy for repeated references 
    typename Base<T>::value_type get(); 

    // Version 3: OK, but unwieldy for many types or deep inheritance 
    typedef typename Base<T>::value_type value_type; 
    value_type get(); 

    // Version 4: why doesn't this work? 
    using typename Base<T>::value_type; 
    value_type get(); // GCC: `value_type' is not a type 
}; 

Tôi có một lớp cơ sở với tập hợp kiểu chữ phân bổ theo kiểu cấp phát mà tôi muốn kế thừa trong nhiều cấp thừa kế. Các giải pháp tốt nhất tôi đã tìm thấy cho đến nay là phiên bản 3 ở trên, nhưng tôi tò mò tại sao Phiên bản 4 dường như không hoạt động. GCC chấp nhận việc sử dụng khai báo, nhưng dường như bỏ qua nó.

Tôi đã kiểm tra C++ Standard, C++ Prog. Lang. Ed thứ 3 [Stroustrup], và C++ Templates [Vandevoorde, Josuttis], nhưng dường như không có địa chỉ cho dù việc sử dụng khai báo có thể được áp dụng cho các loại lớp cơ sở phụ thuộc hay không.

Trong trường hợp nó giúp xem ví dụ khác, here is the same question being asked, nhưng không thực sự được trả lời, trong danh sách gửi thư của GCC. Người hỏi chỉ ra rằng anh ta đã thấy 'sử dụng tên tệp' ở nơi khác, nhưng GCC dường như không hỗ trợ nó. Tôi không có trình biên dịch phù hợp khác để kiểm tra nó.

+0

Đăng một số mã cần biên dịch (theo ý kiến ​​của bạn) để tuân thủ các trình biên dịch, nhưng không. Và đăng cách bạn đang sử dụng mẫu. –

+0

Tôi tin rằng tất cả thông tin liên quan đều ở trên. Phiên bản 1-4 hoạt động trên MSVC 9, có độ phân giải tên một giai đoạn không phù hợp (tức là tại thời điểm khởi tạo). Chỉ có phiên bản 2 & 3 hoạt động trên GCC 4.3. Tôi không biết lý do nào Phiên bản 4 sẽ không hợp lệ, nhưng GCC sẽ không chấp nhận nó. Đối với việc sử dụng, nó không thực sự quan trọng làm thế nào điều này được khởi tạo. Tôi chỉ đang cố gắng để có được bản khai mẫu để biên dịch. Đoạn mã trên là một sự đơn giản hóa của một bộ điều hợp container phức tạp hơn nhiều. –

+0

Khi đăng mã ở đây, đừng mong đợi mọi người phải chỉnh sửa mã để biên dịch mã. –

Trả lời

8

Như Richard Corden chỉ ra, vấn đề này đã được đề cập đến trong C++ Standard Core Language Defect Reports sau khi chuẩn năm 2003 đã được phê chuẩn: How do the keywords typename/template interact with using-declarations?

độ phân giải được đề xuất (tháng 4 năm 2003, sửa đổi tháng 10 năm 2003):

Thêm mới đoạn đến cuối của 7.3.3 [namespace.udecl]:

Nếu khai báo sử dụng sử dụng tên mã từ và chỉ định tên phụ thuộc (14.7.2 [temp.dep]), tên được giới thiệu bởi mã khai báo sử dụng được coi là typedef-name (7.1.3 [dcl.typedef]).

Văn bản này dường như không xuất hiện trong tiêu chuẩn Second Edition từ ngày 15 tháng 10, 2003.

GCC vẫn chưa thực hiện nghị quyết này, như được giải thích trong bug 14258:

- ----- Chú thích # 3 Từ Giovanni Bajo 2004-02-27 12:47 [trả lời] ------- Vấn đề là USING_DECL của chúng tôi không ghi lại "typename", đó là thực tế rằng nó là một loại được nhập khẩu thông qua nó. Điều này được sử dụng để làm việc nhờ vào tên loại ngầm ẩn số , tôi tin.

Duplicate bug 21484 cho biết rằng 'using typename' hoạt động trên Comeau và Intel compilers. Bởi vì MSVC xử lý tất cả các tên là phụ thuộc, cấu trúc là không cần thiết (nhưng được phép) cho trình biên dịch đó.


Fixed trong GCC 4.7 vào ngày 13 tháng 12 năm 2011!

+1

Đây là một lỗi, nhưng chỉ tương đối gần đây, vì vậy tôi nghĩ bạn không nên quá khó với gcc. Vấn đề cốt lõi sau đây nêu bật sự thay đổi từ ngữ "http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#11". Điều này đã đi vào tiêu chuẩn C++ '03. –

+0

Cảm ơn, Richard, đó là liên kết chính xác mà tôi đang tìm kiếm! –

-1

Bạn không bao gồm thông số truy cập (công khai/được bảo vệ/riêng tư) trong mẫu cho Cơ sở trước khi khai báo typedef cho Base :: value_type. Kết quả là, nó mặc định là riêng tư và không thể truy cập trong các lớp bắt nguồn từ Base.

+5

Anh ấy đã định nghĩa các kiểu Base/Derived của mình làm cấu trúc, vì vậy các thành viên của chúng là * public * theo mặc định, không phải riêng tư. – luke

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