Member function templates instantiation in gcc

Hi,

I have a problem with class member function templates. It seems that gcc is trying to analyze the code semantically too early, without explicit template instantiation.

Let the code speak

A.h:
1
2
3
4
5
6
7
8
9
10
11
12
#ifndef __A_H__
#define __A_H__
class A {
public:
	A* ptr;

	template<class T>
	void method() {
		((B*) ptr)->invoke();
	}
};
#endif 


B.h:
1
2
3
4
5
6
7
8
9
10
#ifndef __B_H__
#define __B_H__
#include<iostream>
class B : public A {
        public:
        void invoke() {
                std::cout << "lol" << std::endl;
        }
};
#endif 


C.h:
1
2
3
4
5
6
7
#ifndef __C_H__
#define __C_H__

class C : public A {
	
};
#endif 

C.cpp:
1
2
3
#include"A.h"
#include"B.h"
#include"C.h" 


main.cpp:
1
2
3
4
5
6
7
8
9
10
11
#include "A.h"
#include "B.h"
#include "C.h"

int main()
{
	A a;
	a.ptr = new B();
	a.method<int>();
	return 0;
}


In Visual studio 2010 this code comples fine. However, g++ seems to make too eager template instantiation because even when compiling just C.cpp:
 
g++ -o c.cpp.o -c C.cpp


I get the error about unknown identifier B:
1
2
3
4
5
In file included from C.cpp:1:0:
A.h: In member function ‘void A::method()’:
A.h:10:5: error: ‘B’ was not declared in this scope
A.h:10:7: error: expected primary-expression before ‘)’ token
A.h:10:9: error: expected ‘)’ before ‘ptr’


It seems, that g++ tries to analyse templated function member not only syntactically but also semantically, even though I didn't told it to (I never tried to instantiate the member function template).

Am I missing something? Which compiler is behaving correctly according to the standard?
Visual Studio has the bug, not gcc. All symbols must be declared before being used, therefore B.h must include A.h and C.h must include A.h.
Includes are not the problem here. As You can see in C.cpp all needed symbols are present. My concern is however about A::method(). Why gcc even tries to compile this method if I never requested template instantiation? (I'm talking about compiling only C.cpp). If gcc is tring to compile A::method() when compiling C.cpp, what does it use as template parameter T?

In main.cpp however, all symbols are also present in line 9 where I request template instantiation. Doesn't C++ standard state that templates are instantiated on request? If so, class B is present, declared and defined.
gcc isn't trying to compile it. It is performing some simple syntactic checks. For all the compiler knows, A could be a typedef for int or the constant value 42 or a string or... in which case there is a syntax error at the declaration of class B.

EDIT: I'm barking up the wrong tree slightly. After looking at your error message more closely, the compiler is complaining about this: ((B*) ptr)->invoke(); not because of the derivation. But the problem is the same: A.h is not self-standing because it does not include a definition of B. B's definition may not come after A's definition ever, even when it is inside a template function. This happens because you include A.h before B.h, but you well can't change that order since B depends on A. The answer is to forward declare B in A.h.

Last edited on
Forward declare is not enough, (invalid use of incomplete type ‘struct B’)
1
2
3
4
5
6
7
8
9
//A.h
class A{
	template<class T>
	void method();  //declaration of methods
}

#include "B.h"
template<class T>
void A::method(){ //definition of methods that uses B 
Wow, nice solution. Thanks.
Topic archived. No new replies allowed.