Подтвердить что ты не робот

Ошибка параметра шаблона g++

У меня есть функция 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++ не настолько разрешительный. Что не так с кодом?

4b9b3361

Ответ 1

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

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

Если вы хотите вызвать функцию 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 может быть определен в базовом классе, и поэтому он откладывает поиск до создания шаблона.

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

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