Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

g++ template parameter error

Tags:

c++

templates

g++

I have GetContainer() function as follows.

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

When I use this method as follows

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

I got errors.

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)

It works fine with MSVC, but g++ is not so permissive. What's wrong with the code?

like image 574
prosseek Avatar asked Mar 13 '11 02:03

prosseek


People also ask

What is a template template parameter in C++?

In C++ this can be achieved using template parameters. A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

Which is correct example of template parameters?

For example, given a specialization Stack<int>, “int” is a template argument. Instantiation: This is when the compiler generates a regular class, method, or function by substituting each of the template's parameters with a concrete type.

What are template parameters?

In UML models, template parameters are formal parameters that once bound to actual values, called template arguments, make templates usable model elements. You can use template parameters to create general definitions of particular types of template.

What is the validity of template parameters?

What is the validity of template parameters? Explanation: Template parameters are valid inside a block only i.e. they have block scope.


1 Answers

I noticed that the GetContainer function is a method of ObjCollection, while Insert is a member of DynamicObjectCollection. From this, I'm going to assume that DynamicObjectCollection inherits from ObjectCollection.

If this is indeed the case, the problem is that when you write a template class that inherits from a template base class, the way that name lookup works is slightly different from name lookup in normal classes. In particular, you cannot just reference base class members using their names; you need to indicate to the compiler where to look for the name. The reason this works in Visual Studio is that the Microsoft C++ compiler actually gets this behavior wrong and allows code that is technically illegal to compile just fine.

If you want to invoke the GetContainer function of the base class, you have two options. First, you can explicitly indicate that the call is to a member function:

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

Now that the compiler knows that GetContainer is a member of DynamicObjectCollection, it knows that it might need to look up GetContainer in the base class, and so it will defer name lookup until the template is instantiated.

The other option available would be to add a using declaration into the class body:

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

    /* ... */
};

This also indicates unambiguously to the compiler that GetContainer may be defined in the base class, and so it defers lookup until template instantiation.

If this isn't applicable to your situation, let me know and I can delete this post.

Hope this helps!

like image 132
templatetypedef Avatar answered Sep 17 '22 16:09

templatetypedef