Ошибка параметра шаблона g ++ - PullRequest
16 голосов
/ 13 марта 2011

У меня есть функция GetContainer () следующим образом.

template<typename I,typename T,typename Container>
Container& ObjCollection<I,T,Container>::GetContainer()
{
    return mContainer;
}

Когда я использую этот метод следующим образом

template<typename I,typename T>
T& DynamicObjCollection<I,T>::Insert(T& t)
{
    GetContainer().insert(&t);
    return t;
}

Я получил ошибки.

error: there are no arguments to ‘GetContainer’ that depend on a template parameter, 
so a declaration of ‘GetContainer’ must be available

error: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of 
an undeclared name is deprecated)

Отлично работает с MSVC, но g ++ не так уж и разрешителен. Что не так с кодом?

1 Ответ

53 голосов
/ 13 марта 2011

Я заметил, что функция GetContainer является методом ObjCollection, а Insert является членом DynamicObjectCollection.Исходя из этого, я буду предполагать, что DynamicObjectCollection наследуется от ObjectCollection.

Если это действительно так, проблема заключается в том, что когда вы пишете класс шаблона, который наследуется от базового класса шаблона,способ поиска имени немного отличается от поиска имени в обычных классах.В частности, вы не можете просто ссылаться на членов базового класса, используя их имена;вам нужно указать компилятору, где искать имя.Причина, по которой это работает в Visual Studio, заключается в том, что компилятор Microsoft C ++ на самом деле неправильно понимает это поведение и позволяет просто нормально скомпилировать код, технически недопустимый для компиляции.

Если вы хотите вызвать функцию GetContainer базового классаУ вас есть два варианта.Во-первых, вы можете явно указать, что вызов относится к функции-члену:

this->GetContainer().insert(&t);

Теперь, когда компилятор знает, что GetContainer является членом DynamicObjectCollection, он знает, что может потребоваться поискатьGetContainer в базовом классе, и поэтому он будет откладывать поиск имени, пока не будет создан экземпляр шаблона.

Другой доступный вариант - добавить объявление using в тело класса:

template <typename I, typename T>
class DynamicObjectCollection: public ObjectCollection<I, T, /* ? */> {
public:
    using ObjectCollection<I, T, /* ? */>::GetContainer;

    /* ... */
};

Это также однозначно указывает компилятору, что GetContainer может быть определено в базовом классе, и поэтому откладывает поиск до создания экземпляра шаблона.

Если это не применимо к вашей ситуации, позвольте мнезнаю, и я могу удалить это сообщение.

Надеюсь, это поможет!

...