2011-02-03 5 views
7

Ааа, C++ шаблоны ...Каков смысл этой ошибки «не хватает аргументов шаблона» C++

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

Следующий код компилируется и работает, как ожидалось, но если вы раскомментировать что #define, вы получите сообщение об ошибке , чего я не понимаю. Символ iterator все еще имеет только одну вещь, на которую он может ссылаться: typedef в суперклассе. Итак, у меня есть два вопроса: 1. Что означают ошибки? 2. Каков наилучший способ их исправить.

#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")); 
} 

Ошибки из 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

Вы пробовали струнный :: итератор? – Lordalcol

ответ

4

Вы должны изменить MyClass :: метод haskey тоже.

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

Объяснение такого поведения находится в разделе «Имя поиске, шаблонах и доступе к членам базового класса» на http://physics.ucsd.edu/students/courses/winter2008/physics141/manuals/rhel-gcc-en-4/c---misunderstandings.html (ссылку с комментарием другого ответа, в всяком случае).

Всего неподвижного пример код: http://ideone.com/G7Rty

+1

Спасибо. Я бы отметил это как ответ, но это не объясняет причину ошибки. Это объяснение находится в ссылке в другом ответе. –

+0

Эта ссылка повреждена или за платной. Любые современные ссылки? –

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

Эта линия должна быть,

#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

Вы забыли 'typename'. –

+0

@Nawaz, так производный класс не может видеть базовый класс typedefs? – UmmaGumma

+0

@Ashot: Когда базовый класс является шаблоном, компилятор не может знать во время синтаксического анализа, действительно ли класс содержит этот typedef или нет. Следовательно, вы должны явно использовать typename для ссылочных типов. – Puppy

Смежные вопросы