2012-06-30 17 views
32

Hãy xem xét các tập tin tiêu đề sau đây:C++ template typename iterator

template <typename T> struct tNode 
{ 
    T Data;      //the data contained within this node 
    list<tNode<T>*> SubNodes;  //a list of tNodes pointers under this tNode 

    tNode(const T& theData) 
    //PRE: theData is initialized 
    //POST: this->data == theData and this->SubNodes have an initial capacity 
    //  equal to INIT_CAPACITY, it is set to the head of SubNodes 
    { 
     this->Data = theData; 
     SubNodes(INIT_CAPACITY); //INIT_CAPACITY is 10 
    } 

}; 

Bây giờ hãy xem xét một dòng mã từ tập tin khác:

list<tNode<T>*>::iterator it(); //iterate through the SubNodes 

Trình biên dịch được đem lại cho tôi thông báo lỗi này: Tree.h:38:17: error: need ‘typename’ before ‘std::list<tNode<T>*>::iterator’ because ‘std::list<tNode<T>*>’ is a dependent scope

Tôi không biết tại sao trình biên dịch lại la mắng tôi vì điều này.

Trả lời

54

trong list<tNode<T>*>::iterator, bạn có một tên phụ thuộc, có nghĩa là, một tên mà phụ thuộc vào một tham số mẫu.

Như vậy, trình biên dịch không thể kiểm tra list<tNode<T>*> (nó không có định nghĩa của nó tại điểm này) và vì vậy nó không biết liệu list<tNode<T>*>::iterator là trường tĩnh hay kiểu.

Trong tình huống như vậy, trình biên dịch giả định rằng đó là trường, vì vậy trong trường hợp của bạn, nó tạo ra lỗi cú pháp. Để giải quyết vấn đề này, chỉ nói với trình biên dịch rằng nó là một loại bằng cách đặt một trước typename của việc kê khai:

typename list<tNode<T>*>::iterator it 
5

list<tNode<T>*>::iterator là tên phụ thuộc, loại phụ thuộc vào thông số mẫu. Để khai báo biến đó, bạn cần phải sử dụng typename keyword:

typename list<tNode<T>*>::iterator it = ...; 
16

Thứ nhất, như câu trả lời khác đã lưu ý, tên kiểu lồng nhau thành các loại phụ thuộc cần phải được thêm vào phía trước với typename từ khóa.

Đó từ khóa không cần thiết khi mẫu là hoàn toàn chuyên ngành, có nghĩa là list<tnode<int>*>::iterator không cần typename, nhưng khi các lớp bên ngoài vẫn còn phụ thuộc vào tham số mẫu T, typename phải có mặt.

template <typename T> void foo() { 
    list<tnode<int>*>::iterator it1; // OK without typename 
    typename list<tnode<T>*>::iterator it2; // typename necessary 
} 

Thứ hai, ngay cả với typename tờ khai

typename list<tNode<T>*>::iterator it(); 

sẽ tuyên bố một chức năng, không phải là một iterator. Xóa (). backround

1

Thông tin thêm về các câu trả lời trên được cung cấp ở đây

A Description of the C++ typename keyword

Tôi đã có một vấn đề khác nhau nhưng giống nhau ở chỗ tôi muốn typedef một iterator cho nút con với:

typedef std::vector<NodeType*>::iterator ChildIterator; 

đã cho tôi lỗi trình biên dịch tương tự. Với các đề xuất ở đây và trợ giúp của liên kết ở trên, giải pháp cho vấn đề của tôi là sử dụng

typedef typename std::vector<NodeType*>::iterator ChildIterator; 

thay thế.