I've two different template classes, one of them using as parameter an object of the another template class. i'm getting an error message: collect2: ld returned 1 exit status make: * [main] Error 1
I'm working with explicit instantiation of templates and I found some related posts but they were mostly related to instantiations of one single template class. In my case, I've 3 files per class (.h, .cpp, .inc following http://www.parashift.com/c++-faq/templates.html#faq-35.13 suggestion).
foo.h
#ifndef FOO_H
#define FOO_H
template < class S >
class Foo{
public: ...
private: ...
};
#endif
foo.cpp
...
template < class S >
Foo<S>::Foo(){ .... }
...
#include "foo.inc"
foo.inc
template class Foo<int>;
template class Foo<float>;
开发者_Python百科
bar.h
#ifndef BAR_H
#define BAR_H
#include <mylib.h>
template < class T >
class Bar{
public: ...
template <class S>
void doSomething(Foo<S>*);
private: ...
};
#endif
bar.cpp
....
template <class T> template <class S>
void Bar<T>::doSomething(Foo<S>*p){
....
}
.....
#include "bar.inc"
bar.inc
template class Bar<int>;
template class Bar<float>;
template void Bar<int>::doSomething(Foo<int>*);
template void Bar<float>::doSomething(Foo<float>*);
mylib.h
#include <foo.h>
#include <bar.h>
main.cpp
#include <mylib.h>
#include <common.h>
int main(){
Foo<float> * pFoo = NULL;
pFoo = new Foo<float>();
Bar<float> * pBar = NULL;
pBar = new Bar<float>();
pBar->doSomething(pFoo);
delete pFoo;
delete pBar;
return (0);
}
Does anybody see any problem/bug on the way I'm instantiating the objects? The complete error message is (I changed the name of the classes and simplified the code so as to be more understandable):
g++ -O3 -Wall main.cpp -o ../bin/main -I../inc -L../lib -lmylib -lm
/tmp/cciJHsKr.o: In function `main':
main.cpp:(.text+0x19f): undefined reference to `void Bar<float>::doSomething<float>(Foo<float>*)'
collect2: ld returned 1 exit status
make: *** [main] Error 1
Note that, I compile both foo.cpp and bar.cpp separately, since I'm generating a library.
// Makefile for foo.cpp & bar.cpp
INC=./inc
SRC=./src
LIB=./lib
OBJ=./obj
CC=g++
CFLAGS=-O3 -Wall
mylib: $(LIB)/mylib.a
echo "mylib was created!..."
$(LIB)/mylib.a: \
$(OBJ)/bar.o \
$(OBJ)/foo.o
ar csr $(LIB)/mylib.a \
$(OBJ)/bar.o \
$(OBJ)/foo.o \
$(OBJ)/bar.o: $(SRC)/bar.cpp
$(CC) -c $(CFLAGS) $(SRC)/bar.cpp -I$(INC) \
-o $(OBJ)/bar.o
I solve the problem!
bar.h
#ifndef BAR_H
#define BAR_H
#include <mylib.h>
template < class T >
class Bar{
public: ...
template <class fooType>
void doSomething(fooType*);
private: ...
};
#endif
bar.cpp
#include <bar.h>
#include <foo.h>
...
...
template <class T> template <class fooType>
void Bar<T>::doSomething(fooType*p){
....
}
.....
#include "bar.inc"
bar.inc
#include <foo.h>
template class Bar<int>;
template class Bar<float>;
template void Bar<int>::doSomething(Foo<int>*);
template void Bar<float>::doSomething(Foo<float>*);
I haven't got a environment with GCC setup at the moment, so I'm flying blind here.
There seems to be a few problems with your code (as my mental compiler sees it).
In bar.cpp you haven't scoped the
doSomething()
function. Given it has been declared in a separate header you needBar::doSomething()
. Given Bar is templated you also need to provide a binding i.e.Bar<T>::doSomething()
.In bar.cpp the template bindings appear to be the wrong way around (they can be arbitrary in your example, but), for clarify I would change them around so that it is the following:
template <class T> template <class S> void Bar<T>::doSomething(Foo<S>*p){ ... }
Finally the
main()
has a problem, in that you are not creating aFoo
object on the heap - I think the compiler should catch this (assigningFoo
toFoo*
). I guess you've just missed thenew
keyword out.pFoo = new Foo<float>();
精彩评论