Reputation: 1141
I'm trying to overload the "<<" operator for a template class. I've the definition of the class in a .h file and its implementation in a .cpp file.
/tmp/ccjJIJhO.o: In function `main':
main.cpp:(.text+0xad): undefined reference to `std::basic_istream<char, std::char_traits<char> >& operator>><int>(std::basic_istream<char, std::char_traits<char> >&, FeatureVector<int>&)'
main.cpp:(.text+0xba): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& operator<< <int>(std::basic_ostream<char, std::char_traits<char> >&, FeatureVector<int> const&)'
collect2: ld returned 1 exit status
The class definition:
#include <iostream>
using namespace std;
#ifndef FEATURE_VECTOR_H
#define FEATURE_VECTOR_H
#include <common.h>
template < class FEAT_TYPE >
class FeatureVector;
template < class FEAT_TYPE >
istream & operator >> (istream &, FeatureVector<FEAT_TYPE> &);
template < class FEAT_TYPE >
ostream & operator << (ostream &, const FeatureVector<FEAT_TYPE> &);
template < class FEAT_TYPE >
class FeatureVector{
public:
FeatureVector(int = 0);
...
friend istream & operator >> <>(istream &, FeatureVector<FEAT_TYPE> & );
friend ostream & operator << <>(ostream &, const FeatureVector<FEAT_TYPE> &);
...
~FeatureVector();
private:
int m_nDim;
FEAT_TYPE * m_pFeat;
};
#endif
#include <featurevector.h>
...
template < class FEAT_TYPE >
istream & operator >> (istream & input, FeatureVector< FEAT_TYPE> & refFeat ){
int d;
for(d=0; d < refFeat.getDim(); d++){
input >> refFeat.m_pFeat[d];
}
return (input);
}
template < class FEAT_TYPE >
ostream & operator << (ostream & output, const FeatureVector< FEAT_TYPE > & refFeat ){
int d;
for(d=0; d < refFeat.getDim(); d++){
output << refFeat.m_pFeat[d] << " ";
}
output << endl;
return (output);
}
...
#include "featurevector-impl.cpp"
template class FeatureVector<int>;
//template istream & operator >> <>(istream &, FeatureVector<int> &);
//template ostream & operator << <>(ostream &, const FeatureVector<int> &);
#ifndef MY_LIB_H
#define MY_LIB_H
#include <featurevector.h>
#endif
#include <mylib.h>
#include <common.h>
int main(){
FeatureVector<int> pFeat(10);
cin >> (pFeat);
cout << (pFeat);
return (0);
}
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)/featurevector.o
ar csr $(LIB)/mylib.a \
$(OBJ)/featurevector.o
$(OBJ)/featurevector.o: $(SRC)/featurevector.cpp
$(CC) -c $(CFLAGS) $(SRC)/featurevector.cpp -I$(INC) \
-o $(OBJ)/featurevector.o
clean:
rm -rf $(LIB)/*.a
rm -rf $(OBJ)/*.o
LIB=../lib
INC=../inc
OBJ=../obj
BIN=../bin
CC=g++
CFLAGS=-O3 -Wall
LFLAGS=-lmylib -lm
[email protected]: $(LIB)/mylib.a [email protected]
cd ..; make; cd app;
$(CC) $(CFLAGS) [email protected] -o $(BIN)/$@ -I$(INC) -L$(LIB) $(LFLAGS)
clean:
rm -rf $(BIN)/*
Upvotes: 3
Views: 10895
Reputation: 1884
According to this, you have to make the function known as template in your class definition.
class.h
#include <iostream>
using std::ostream;
template <typename T>
class A {
public:
...
template <typename J> // <-- CAUTION!
friend ostream &operator<<(ostream &output, const A<J> &a);
};
class.cpp
#include "class.h"
...
template <typename T>
ostream &operator<<(ostream &output, const A<T> &a) {
// Your implementation
return output;
}
...
template ostream &operator<<(ostream &output, const A<int> &a);
template ostream &operator<<(ostream &output, const A<float> &a);
If the line template <typename J>
is removed, the compilation error "underfined reference" comes.
Upvotes: 5
Reputation: 145269
See FAQ item 35.12 Why can't I separate the definition of my templates class from its declaration and put it inside a .cpp file?.
Upvotes: 2
Reputation: 8516
featurevector-impl.cpp is incorrect. Explicit template instantiations look like this:
template class FeatureVector<int>;
Since the operators aren't members, they must also be explicitly instantiated:
template istream & operator >> <>(istream &, FeatureVector<int> &);
I don't recommend splitting up your template definitions like this, though, unless you're really keen on micromanaging which specific classes will work with your template (which kind of goes against the spirit of using a template).
Upvotes: 0
Reputation:
Don't make it so complicated:
template<class FEAT_TYPE>
struct FeatureVector {
FeatureVector(int = 0);
friend std::istream& operator>>(std::istream &s, FeatureVector &x) {
for(int d = 0; d < x.getDim(); d++) {
s >> x.m_pFeat[d];
}
return s;
}
friend std::ostream& operator<<(std::ostream &s, FeatureVector const &x) {
// since you're terminating with " " rather than separating:
copy(x.m_pFeat, x.m_pFeat + x.getDim(), ostream_iterator<FEAT_TYPE>(s, " "));
s << endl;
return s;
}
//...
Upvotes: 0
Reputation: 101456
Your posted error code says that it is operator>>
that is throwing an unresolved external error, not operator<<
. In addition, your code won't compile because there is no convert constructor on myClass
taking an int
. So you have not posted the correct code.
But this works:
#include <iostream>
using namespace std;
template < class T >
class myClass;
template < class T >
ostream & operator << (ostream &, const myClass<T> &);
template < class T >
class myClass{
public:
myClass(int) {}
friend ostream & operator << <>(ostream &, const myClass<T> &);
private:
T m_Data;
};
template < class T >
ostream & operator << (ostream & out, const myClass<T> & refClass){
out << refClass.m_Data << endl;
return (out);
}
myClass<int>;
myClass<float>;
int main(int argc, char **argv){
myClass<int> test(5);
cout << test;
return 0;
}
Upvotes: 1