2010-03-23 24 views
5

Tôi có mẫu Vertex ở đỉnh.h. Từ biểu đồ của tôi.h:Điều gì làm cho "người khai báo không hợp lệ" này? C++

20 template<class edgeDecor, class vertexDecor, bool dir> 
21 class Vertex; 

mà tôi sử dụng trong mẫu Đồ thị của mình.

Tôi đã sử dụng mẫu Vertex thành công trong suốt Biểu đồ, trả về con trỏ tới Đỉnh, v.v. Lần đầu tiên tôi cố gắng khai báo và khởi tạo đối tượng Vertex và gcc cho tôi biết rằng 'người khai báo' của tôi là 'không hợp lệ'. Làm sao có thể?

81 template<class edgeDecor, class vertexDecor, bool dir> 
82 Graph<edgeDecor,int,dir> Graph<edgeDecor,vertexDecor,dir>::Dijkstra(vertex s, bool print = false) const 
83 { 
84 /* Construct new Graph with apropriate decorators */ 
85 Graph<edgeDecor,int,dir> span = new Graph<edgeDecor,int,dir>(); 
86 span.E.reserve(this->E.size()); 
87 
88 typename Vertex<edgeDecor,int,dir> v = new Vertex(INT_MAX); 
89 span.V = new vector<Vertex<edgeDecor,int,dir> >(this->V.size,v); 
90 }; 

Và gcc đang nói:

graph.h: In member function ‘Graph<edgeDecor, int, dir> Graph<edgeDecor, vertexDecor, dir>::Dijkstra(Vertex<edgeDecor, vertexDecor, dir>, bool) const’: 
graph.h:88: error: invalid declarator before ‘v’ 
graph.h:89: error: ‘v’ was not declared in this scope 

Tôi biết điều này có lẽ là một câu hỏi noob, nhưng tôi sẽ đánh giá cao sự giúp đỡ nào.

+0

Có lẽ không liên quan đến vấn đề này, nhưng bạn có chắc chắn muốn "= Vertex mới (INT_MAX)" không? Bạn có lẽ có nghĩa là "đỉnh" uncapitalised (mà tôi giả định là một typedef)? Ngoài ra Vertex <...> thực sự có một ctor lấy một con trỏ Vertex/đỉnh? –

Trả lời

1

Igor là đúng. Đối với các lỗi sau:

graph.h:88: error: expected type-specifier before ‘Vertex’ 

... có lẽ bạn cần phải nói:

Vertex<edgeDecor,int,dir> v = new Vertex<edgeDecor,int,dir>(INT_MAX); 
+0

Điều đó đã giải quyết được. Cảm ơn. –

4

Có lẽ cần phải được

Vertex<edgeDecor,int,dir> v = new Vertex(INT_MAX); 

bởi vì bạn đang khai báo một thể hiện của Vertex. typename từ khóa chỉ hợp lệ trong danh sách tham số mẫu.

Cảm ơn Abhayoutis để chỉ ra sử dụng hợp lệ keyword ngoài danh mục mẫu tham số.

Sau khi có cái nhìn khác về mã một số điều khác tôi suy nghĩ:

  1. Như đã chỉ ra bởi Mike Dinsdale bạn đang thiếu các thông số mẫu tại đây: new Vertex(INT_MAX);. Hãy thử dùng Vertex<edgeDecor,int,dir> để thay thế.
  2. Bạn đang gán một con trỏ cho một cá thể lớp. Nếu bạn đang tạo nó trên ngăn xếp, nó sẽ giống như thế này:

    Vertex v (INT_MAX);

Nếu tạo trên heap v phải loại con trỏ:

Vertex<edgeDecor,int,dir>* v = new Vertex<edgeDecor,int,dir>(INT_MAX); 
+2

"từ khóa tên tệp chỉ hợp lệ trong danh sách tham số mẫu", tôi không nghĩ vậy. Đối với các tên phụ thuộc vào mẫu, hầu hết các trình biên dịch yêu cầu bạn chỉ định * typename *. – Abhay

+0

RE tên phụ thuộc: đọc http://pages.cs.wisc.edu/~driscoll/typename.html. Trong trường hợp của OP, 'Vertex ' không phải là một tên phụ thuộc, do đó, 'typename' không hợp lệ. – outis

+0

Nếu không có từ khóa "typename" gcc, hãy cung cấp: đồ thị.h: 88: lỗi: loại dự kiến-specifier trước 'Vertex' Điều này khiến tôi nghĩ rằng "tên tệp" là bắt buộc ở đây để chỉ ra trình biên dịch mà tôi đang giới thiệu cho một loại. –

0

Như đã nói, đó là một vấn đề đặt không đúng chỗ typename đầu tiên.

Một số ví dụ:

template <class T> 
struct MyClass 
{ 
    struct Foo { static int MBar; }; 
}; 

template <> 
struct MyClass<int> { static int Foo; }; 

Sử dụng MyClass:

template <class T> 
void useMyClass(T t) 
{ 
    MyClass<T> c; 
} 

Không cần của typename vì không có sự mơ hồ, trình biên dịch biết MyClass đã nhận được một loại ở đây.

template <class T> 
void useFoo(T t) 
{ 
    typename MyClass<T>::Foo f; 
} 

Chúng ta cần phải disambiguate vì trình biên dịch không biết trước nếu biểu tượng Foo sẽ là một loại, một phương pháp hay một thuộc tính. Thật vậy, nếu T == int mã này không đúng vì Foo sẽ đại diện cho thuộc tính static thay vì là struct!

void useFoo(int t) 
{ 
    int f = MyClass<int>::Foo; 
} 

void useFoo(float t) 
{ 
    float f = MyClass<float>::Foo::MBar; 
} 

đây typename không được yêu cầu: kể từ khi trình biên dịch biết tất cả các kiểu trong danh sách mẫu tham số, nó có thể nhanh chóng các lớp mẫu cho MyClass<int>MyClass<float> và như đối với một lớp học thường xuyên biết trong ra ngoài của mỗi instantiation (và đặc biệt là những gì mỗi biểu tượng đại diện cho).

template <class T> 
void useBar(T t) 
{ 
    int i = typename MyClass<T>::Foo::MBar; 
} 

Một lần nữa chúng ta cần typenameFoo là một loại và trình biên dịch cần phải biết điều đó.

Nếu bạn không thực sự hiểu, đừng lo lắng. Các từ khóa typenametemplate đôi khi leo ở những nơi khác thường trong mã chung: chỉ cần chờ lỗi trình biên dịch bắt đầu, bạn sẽ sớm ghi nhớ loại lỗi và sửa chúng trong nháy mắt.

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