2010-01-19 28 views
6

Tôi có mã biên dịch tốt với VC9 (Microsoft Visual C++ 2008 SP1) nhưng không phải với GCC 4.2 (trên Mac, nếu có vấn đề). Nếu tôi chồng chất đủ điều kiện và từ khóa tôi có thể buộc nó làm việc trong GCC nhưng điều này có vẻ không đúng.Cú pháp C++ tốt hơn cho các typedef và lớp cơ sở mẫu?

Dưới đây là một mẫu mã tối thiểu trưng bày vấn đề của tôi:

template< typename N > 
struct B { 
    typedef N n_type;      // can derived class access typedef? 
    void foo() {}       // can derived class access function? 
}; 

template< typename N > 
struct D : public B<N> { 

    typedef B<N> b_type; 
    typedef typename b_type::n_type bn_type; 

    void f1(n_type) {}     // ERROR: 'n_type' has not been 
              // declared 

    void f2(typename B<N>::n_type) {} // OK, verbose 

    void f3(b_type::n_type) {}   // ERROR: 'struct B<N>::n_type' is 
              // not a type 

    void f4(typename b_type::n_type) {} // OK, verbose 

    void f5(bn_type) {}     // OK, verbose typedefs 

    void f6() { foo(); }     // ERROR: there are no arguments to 
              // 'foo' that depend on a template 
              // parameter, so a declaration of 
              // 'foo' must be available 

    void f7() { b_type::foo(); }   // OK, verbose 

}; 

Tôi có sai lầm để mong đợi một mẫu lớp có nguồn gốc từ một lớp mẫu để có thể sử dụng typedefs và chức năng thừa hưởng trực tiếp? Có cách nào tốt hơn để làm điều này hơn những gì tôi đã đưa ra cho đến nay?

+0

điểm của 'typedef N n_type' là gì? bạn chỉ có thể sử dụng 'N' trực tiếp – Trent

+3

typedef không được kế thừa, Visual C++ không tuân thủ các tiêu chuẩn thường xuyên. các hàm kế thừa có thể được truy cập bằng cách sử dụng độ phân giải phạm vi, cơ sở IE :: f hoặc this-> f. bạn cũng có thể sử dụng "using base :: f" để đưa hàm vào phạm vi cục bộ. – Anycorn

+0

Nó hoạt động cho tôi ngoại trừ trường hợp của f3. –

Trả lời

9

Tôi có sai khi mong đợi một lớp mẫu có nguồn gốc từ một lớp mẫu khác để có thể sử dụng trực tiếp các hàm typedef và hàm được kế thừa không?

Có, điều này thường sẽ không hoạt động như bạn mong đợi. Các quy tắc tra cứu tên C++ xác định rằng tên chỉ được tìm kiếm trong một lớp cơ sở templated nếu nó phụ thuộc vào tham số mẫu (nếu nó là "tên phụ thuộc"). Nếu một tên không phụ thuộc vào một tham số mẫu thì nó không được tìm kiếm ở đó. (Xem thêm this C++ FAQ Lite entry)

Để gọi chức năng từ một lớp cơ sở phụ thuộc một cách dễ dàng nhất là sử dụng this->, vì this luôn ngầm một tên phụ thuộc:

void f6() { this->foo(); } 
+1

'this' không giúp ích gì với' n_type', nhưng ồ, đó là cách thực hiện. – ephemient

+1

Bạn có thể thêm 'typedef typename B :: n_type n_type;' để có được một loại 'n_type' đề cập đến điều đúng, nhưng có lẽ tốt hơn là phải rõ ràng ở đó. – sth

2

Không có loại n_type. Có (hoặc có thể) một loại với tên đó phụ thuộc vào N. Vì vậy, không, bạn không thể làm những gì bạn muốn.

3

Xem C++ FAQ Lite § 35.18-20C++ Templates FAQ.

Tra cứu tên hai pha là một phần phức tạp của C++ khiến nhiều trình biên dịch (và lập trình viên) bị sai. Nó đủ để nói, GCC là chính xác hơn (theo đặc tả C++) hơn MSVC là ở đây, và không có, không có cách nào tốt hơn để làm những gì bạn muốn.

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