Re: Code compiles with g++ 3.3 but not g++ 4.4

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Dave,
> > Sorry, my mistake.
> > template class Graph<int,int,int>::Graph(int, int, void (*)(char *));
> > was wrong;-) the "class" was too much. Try only
> > template Graph<int,int,int>::Graph(int, int, void (*)(char *));
> Ah, great, thanks!
> Ok this problem is solved, but it inspired a more general question. I never
> understood why you have to explicitly instantiate these template
> classes/functions? I thought that NOT knowing which types were going to be
> used before hand was kind of the whole point? Why can't the compiler just
> figure out which types you are trying to use the template class/function
> with and just instantiate it for you?
Read the C++-Standard §14.7.1 Implicit instantiation ;-)

Well, the problem is the following:
If you have the definitions of the Memberfunctions in one file (e.g.
Graph.cpp) and USE the graph in another file (Example.cpp) and you
compile both files independently:
How can the compiler know when you are compiling "Graph.cpp" that you
will later use Graph<int,int,int>?
And when you are compiling "Example.cpp", the compiler has no access to
the function definitions stored in Graph.cpp - so it can't create the
functions for "Graph<int,int,int>".
So: you are stuck:-)

If you want it to happen automatically, it is necessary that the
compiler has access to all template function definitions (Graph.cpp)
while it is compiling a routine which is using this definitions. So for
your example: Simply '#include "Graph.cpp"' into Example.cpp

Than you don't need any longer "instances.inc", but the compiler will
instead instanciate the templates as needed:
For your files:
graph.h is unchanged.
graph.cpp: erase the '#include "instances.inc"'
example.cpp: 'include "graph.cpp"' instead of graph.h.

graph.h: 
#ifndef GRAPH_H
#define GRAPH_H
#include <cstdlib> //for NULL
template <typename captype, typename tcaptype, typename flowtype> class
Graph
{
public:
	Graph(int node_num_max, int edge_num_max, void
(*err_function)(char *) = NULL);
};
#endif

graph.cpp:
#include "graph.h"
//constructor
template <typename captype, typename tcaptype, typename flowtype> 
	Graph<captype, tcaptype, flowtype>::Graph(int node_num_max, int
edge_num_max, void (*err_function)(char *))
{
}

example.cpp:
#include "graph.cpp"
int main()
{
	typedef Graph<int,int,int> GraphType;
	GraphType* g = new GraphType(2, 1); 
	return 0;
}

Then, the compiler will do everything for you - it is sufficient to
compile "graph.cpp". Well, I would recommend you to rename "graph.cpp"
such that you know it's a file that will be #include'd - but that's not
necessary.

HTH,

Axel

[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux