2009-05-24 35 views
9

Tại sao mã sau đây cho tôi lỗi (g ++ 4.1.2)?Chức năng thành viên được đánh dấu có giá trị trả về typedef

template<class A> 
class Foo { 
public: 
    typedef std::vector<A> AVec; 
    AVec* foo(); 
}; 

template<class A> 
Foo<A>::AVec* Foo<A>::foo() { // error on this line 
    return NULL; 
} 

Lỗi này là:

error: expected constructor, destructor, or type conversion before '*' token 

Làm sao tôi phải xác định Foo<A>::foo() chức năng khác (với kiểu trả về đúng)?

Trả lời

17

Đây là vấn đề được gọi là "two-stage lookup". Về cơ bản, vì A là một tham số mẫu theo định nghĩa của foo(), trình biên dịch không thể biết khi phân tích mẫu lần đầu tiên, cho dù Foo<A>::AVec là một loại hoặc thậm chí tồn tại (vì, ví dụ, có thể tồn tại một chuyên ngành của Foo<Bar> mà không chứa typedef ở tất cả). Nó sẽ chỉ biết những gì nó là trong mẫu instantiation, điều này xảy ra sau đó - và đã quá muộn cho giai đoạn này.

Cách đúng sẽ được sử dụng từ khóa typename để cho biết rằng đây là một loại:

template<class A> 
class Foo { 
public: 
    typedef std::vector<A> AVec; 
    AVec* foo(); 
}; 

template<class A> 
typename Foo<A>::AVec* Foo<A>::foo() { 
    return NULL; 
} 
-1

Tôi không thực sự biết, nhưng hãy thử đặt typedef bên ngoài lớp học.

13

Trường hợp phổ typename vấn đề:

template<class A> 
typename Foo<A>::AVec* Foo<A>::foo() { // error on this line 
    return NULL; 
} 

Hãy nhớ rằng: Theo nguyên tắc chung, tất cả các trình độ các tên phụ thuộc vào tham số mẫu cần typename trước chúng.

+0

Ngoại trừ trong danh sách lớp cơ sở và khởi tạo lớp cơ sở, nơi tên tệp không được phép. –

+1

@Johan đã được sửa. . –

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