2011-02-03 40 views
7

Ahh, C++ mẫu là gì ...ý nghĩa của 'thiếu mẫu tranh cãi' C++ lỗi này

The code I see,
makes sense to me,
but GCC...
it disagrees.

Các mã sau biên dịch và chạy như mong đợi, nhưng nếu bạn bỏ ghi chú rằng #define, bạn nhận được lỗi mà tôi không hiểu. Biểu tượng iterator vẫn chỉ có một thứ mà nó có thể tham chiếu đến: typedef trong siêu lớp. Vì vậy, tôi đoán tôi có hai câu hỏi: 1. Các lỗi có ý nghĩa gì? 2. Cách tốt nhất để khắc phục chúng là gì.

#include <map> 
#include <string> 
#include <cstdio> 

using namespace std; 

// #define WITH_TEMPLATE 1 

#ifdef WITH_TEMPLATE 
template <class C> 
struct MyClass : public map<string, C> 
#else 
struct MyClass : public map<string, int> 
#endif 
{ 
    bool haskey(const string &s) 
    { 
     iterator it = find(s); 
     return (it != end()); 
    } 
}; 

int main() 
{ 
#ifdef WITH_TEMPLATE 
    MyClass<int> m; 
#else 
    MyClass m; 
#endif 
    m["test"] = 10;  
    printf("%d %d\n", m.haskey("test"), m.haskey("no")); 
} 

lỗi từ GCC:

temp.cc: In member function ‘bool MyClass::haskey(const std::string&)’:
temp.cc:18: error: missing template arguments before ‘it’
temp.cc:18: error: expected `;' before ‘it’
temp.cc:19: error: ‘it’ was not declared in this scope
temp.cc:19: error: there are no arguments to ‘end’ that depend on a template parameter, so a declaration of ‘end’ must be available
temp.cc:19: error: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)

+0

Bạn đã thử chuỗi :: iterator? – Lordalcol

Trả lời

4

Bạn cần thay đổi MyClass bạn :: phương pháp haskey quá.

bool haskey(const string &s) 
{ 
    typename MyClass<C>::iterator it = this->find(s); 
    return (it != this->end()); 
} 

Giải thích về một hành vi như vậy là trong phần "Name tra cứu, các mẫu, và truy cập các thành viên của lớp cơ sở" trên http://physics.ucsd.edu/students/courses/winter2008/physics141/manuals/rhel-gcc-en-4/c---misunderstandings.html (liên kết từ bình luận của câu trả lời khác, chỉ trong trường hợp).

Toàn bộ mã ví dụ cố định: http://ideone.com/G7Rty

+1

Cảm ơn. Tôi đánh dấu đây là câu trả lời, nhưng nó không giải thích lý do cho lỗi. Lời giải thích đó nằm trong một liên kết trong câu trả lời khác. –

+0

Liên kết này bị hỏng hoặc sau tường thuật. Bất kỳ tài liệu tham khảo cập nhật nào? –

3
iterator it = find(s); 
return (it != end()); 

Dòng này nên càng,

#ifdef WITH_TEMPLATE 
      typename map<string, C>::iterator it = this->find(s); 
      return (it != this->end()); 
#else 
      map<string, int>::iterator it = find(s); 
      return (it != end()); 
#endif 
+1

Bạn quên 'typename'. –

+0

@Nawaz nên lớp dẫn xuất không thể nhìn thấy typedefs lớp cơ sở? – UmmaGumma

+0

@Ashot: Khi lớp cơ sở là một khuôn mẫu, trình biên dịch không thể biết tại phân tích thời gian có hay không lớp thực sự chứa typedef đó hay không. Do đó, bạn phải sử dụng tên tệp một cách rõ ràng cho các kiểu tham chiếu. – Puppy

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