template class, friend operator << overload
Solution 1
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.
Solution 2
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?.
Solution 3
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;
}
Javier
Updated on June 04, 2022Comments
-
Javier almost 2 years
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:
common.h
#include <iostream> using namespace std;
featurevector.h
#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
featurevector.cpp
#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"
featurevector-impl.cpp
template class FeatureVector<int>; //template istream & operator >> <>(istream &, FeatureVector<int> &); //template ostream & operator << <>(ostream &, const FeatureVector<int> &);
mylib.h
#ifndef MY_LIB_H #define MY_LIB_H #include <featurevector.h> #endif
main.cpp
#include <mylib.h> #include <common.h> int main(){ FeatureVector<int> pFeat(10); cin >> (pFeat); cout << (pFeat); return (0); }
Makefile associated with "mylib"
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
Makefile for main.cpp (the main.cpp with its Makefile are under an "app" directory)
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)/*
-
John Dibling over 13 yearsI don't think this is the issue. Javier is
#include
-ing the HPP file directly from the H file, yielding the same results as your FAQ link. -
Javier over 13 yearsExactly, I considered the suggestion in the referred link already. Thanks anyway.
-
Javier over 13 yearsHi, as I mentioned, I didn't put the whole class definition. I have of course a default constructor. So, your suggestion is to put everything in the same file? This was the problem? Due to organization purposes, I prefer to keep the files separated.
-
John Dibling over 13 years@Javier: No, ultimately the problem I was having is that your posted error message complained about
operator>>
, notoperator<<
-
John Dibling over 13 years@Javier: Also, it would be very helpful if you could post a minimal and complete example that replicates the problem you are having. Psudocode like you've posted is difficult to work with.
-
Cheers and hth. - Alf over 13 years@John, @Jahvier: I can't see that the definition of the
operator>>
function template is available inmain
. Nor can I see an explicit instantiation of it. If it is, sorry for the noise. But I gather the question wouldn't have been raised if it is. CHeers & hth., -
Javier over 13 yearsHi John, well, I updated already the class, because I was trying to overload both ">>" and "<<" and the similar error was shown.
-
Javier over 13 yearsI edited the class, so the definition of the operator >> is already included.
-
Cheers and hth. - Alf over 13 years@Javier: well, how about telling us whether that got rid of the problem, and if not, posting sort of actual code?
-
Javier over 13 yearsHi Steve, I recently tried your suggestion, but I still have the same error. I updated my initial post, were I included the true class.
-
Javier over 13 yearsIt didn't solve and I also included on my original post the actual code.
-
Steve M over 13 yearsWhat is your compilation command? Are you compiling both main.cpp and featurevector.cpp? (Or main.o and featurevector.o if you compiled them separately)
-
Cheers and hth. - Alf over 13 years@Javier the friend functions, like operator>>, aren't class members. They don't get instantiated by instantiating the class. Cheers & hth.
-
Javier over 13 years@Steve, I'm compiling them separately.
-
Steve M over 13 years@Javier: So when you link them, are you specifying both object files in the command? This compiles, links, and runs for me (even with separate compilation) if I put explicit instantiations for the stream operators in featurevector-impl.cpp.
-
Cheers and hth. - Alf over 13 years@Javier: at the time of my comment, and still as I'm writing this, you're instantiating your class for type
int
. But you're not instantiating the operator templates (which are not part of the class). Since definitions not available inmain
, and since no instantiations, linker error. See FAQ item 35.12 linked to above. Cheers & hth. -
Steve M over 13 years@Alf: This is covered by my answer, but he still seems to be having some kind of problem.
-
Javier over 13 yearsHi Steve, I basically have a small library that contains the featurevector class (so, I generate at this point featurevector.o). Then, when I compile the main, I link the library, sth, like: g++ -O3 -Wall main.cpp -o ../bin/main -I../inc -L../lib -lmylib -lm
-
Javier over 13 years@Steve, it seems to be that the problem is during the linking. Could you please check the Makefile I added in my original post? Do you see sth. strange there?
-
Javier over 13 yearsIt seems to be that the problem is during the linking (from what I found in the internet, g++ & gcc). Could you please check the Makefile I added in my original post? Do you see sth. strange there?