template class, friend operator << overload - c++

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
$#.cpp: $(LIB)/mylib.a $#.cpp
cd ..; make; cd app;
$(CC) $(CFLAGS) $#.cpp -o $(BIN)/$# -I$(INC) -L$(LIB) $(LFLAGS)
clean:
rm -rf $(BIN)/*

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.

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?.

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;
}

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;
}
//...

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).

Related

error: cannot bind ‘std::ostream in implementation file

First: I have tried reading and modifying my code based off no less than 7 other similar questions. At best, the other options trigger an avalanche of errors. With my current code, I'm down to a single error.
Putting it inside the class and using "friend" doesn't work, and using ostream& operator<< (ostream &out, const Fraction &rhs) makes a whole lot more errors.
The frustrating thing is that in c9.io this code works, but not on Netbeans.
In my main.cpp:
#include <iostream>
#include "fraction.h"
using namespace std;
int main() {
Fraction f(3, 4);
cout << f;
return 0;
}
In fraction.h:
#ifndef FRACTION_H
#define FRACTION_H
class Fraction{
public:
//constructor defs
//accessors
//modifiers/mutators
void setNumer(int newNum);
void setDenom(int newDenom);
void reduce();
private:
//instance variables
int numer;
int denom;
//helper functions
int gcd(int a, int b);
};
#endif /* FRACTION_H */
And in fraction.cpp:
#include "fraction.h"
#include <cmath>
#include <iostream>
using namespace std;
//code for constructors
//accessors
int Fraction::getNumer(){
return numer;
}
int Fraction::getDenom(){
return denom;
}
//modifiers/mutators
//other operator definitions
ostream& operator<< (ostream &out, Fraction &rhs){
if(rhs.getNumer() == 0){
out << 0;
} else if(rhs.getNumer() == rhs.getDenom()){
out << 1;
} else {
rhs.reduce();
out << rhs.getNumer() << "/" << rhs.getDenom();
}
}
The output is:
g++ -c -g -std=c++11 -MMD -MP -MF "build/Debug/GNU-Linux/main.o.d" -o build/Debug/GNU-Linux/main.o main.cpp
main.cpp: In function ‘int main()’:
main.cpp:6:13: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
cout << f;
^
In file included from /usr/include/c++/4.8/iostream:39:0,
from main.cpp:1:
/usr/include/c++/4.8/ostream:602:5: error: initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = Fraction]’
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
There is no knowledge of the operator<< function that is defined in Fraction.cpp in main.cpp Hence, the line
cout << f;
is a problem.
Add the declaration of the function in the .h file.
#ifndef FRACTION_H
#define FRACTION_H
#include <iostream>
class Fraction{
public:
//constructor defs
//accessors
//modifiers/mutators
void setNumer(int newNum);
void setDenom(int newDenom);
void reduce();
private:
//instance variables
int numer;
int denom;
//helper functions
int gcd(int a, int b);
};
std::ostream& operator<< (std::ostream &out, Fraction const& rhs);
// ^^^^ Using const&, not just Fraction&
#endif /* FRACTION
So the answer was partly what #r-sahu said:
I had to set getNumer() and getDenom() as const member functions BUT I could only get the errors to go away by NOT using const& in the function definition.
Good:
std::ostream& operator<< (std::ostream &out, Fraction rhs);
Not good:
std::ostream& operator<< (std::ostream &out, Fraction const& rhs);
It now compiles and runs. any insight on why making the member functions const but not passing the Fraction as const makes it work? I stumbled on this solution by accident and don't understand it.

Understanding templates in c++

I am trying run the following program, But it generates compilation error:
#ifndef TEMPLATE_SUM_H_
#define TEMPLATE_SUM_H_
template<typename T>
class sum
{
public:
sum() {
val_1 = 0;
val_2 = 0;
}
sum(T a, T b) {
val_1 = a;
val_2 = b;
}
friend std::ostream& operator<<(std::ostream &, const sum<> &);
private:
T val_1, val_2;
T result() const;
};
#endif
Source file:
include <iostream>
#include "inc/sum.h"
template<typename T>
T sum<T>::result() const {
return (val_1 + val_2);
}
template<typename T>
std::ostream& operator<<(std::ostream& os, const sum<T>& obj) {
//std::ostream& operator<<(std::ostream& os, sum<T>& obj) {
os << obj.result();
return os;
}
int main()
{
sum<int> int_obj(15, 15);
sum<float> float_obj(5.2, 3.5);
std::cout << "result of int = " << int_obj << std::endl;
std::cout << "result of float = " << float_obj << std::endl;
return 0;
}
Compiling with g++ (4.4.3) it generates following error:
In file included from template.cpp:2:
inc/sum.h:18: error: wrong number of template arguments (0, should be 1)
inc/sum.h:5: error: provided for ‘template<class T> class sum’
template.cpp: In function ‘std::ostream& operator<<(std::ostream&, const sum<T>&) [with T = int]’:
template.cpp:20: instantiated from here
template.cpp:5: error: ‘T sum<T>::result() const [with T = int]’ is private
template.cpp:12: error: within this context
template.cpp: In function ‘std::ostream& operator<<(std::ostream&, const sum<T>&) [with T = float]’:
template.cpp:21: instantiated from here
template.cpp:5: error: ‘T sum<T>::result() const [with T = float]’ is private
template.cpp:12: error: within this context
1) Can Anyone please help me in identifying the error ?
Also Please suggest some links where I can find brief absolute details on how to use templates in c++.
2) I read that templatized func/classes declared in header file, and defined separately are prone to linking error. Can anyone explain/elaborate this ?
Is there any possibility of linking error in above example ?
The statement is as below:
"If a template or inline function is declared in a .h file, define it in that same file. The definitions of these constructs must be included into every .cpp file that uses them, or the program may fail to link in some build configurations."
This example can be done in some more easy way, without using overloaded operator etc. But I am trying to learn/practising templates and experimenting some features.
You need to have a separate template definition for the friend function declaration:
template<typename U>
friend std::ostream& operator<<(std::ostream &, const sum<U> &);
friend declarations do not inherit the template parameters of the enclosing class.
A simple sample source, to get started;
Calculator.h
#ifndef CALCULATOR_H
#define CALCULATOR_H
template <class TYPE>
class Calculator{
public:
Calculator();
TYPE Sum(TYPE param1, TYPE param2);
};
/**
* To avoid template related compilation error
* when templates are used in header and source files
*
* This class file has been removed from the project-source file.
* However, is present in the project folder
* Gets compiled with the header-file (being included)
*/
#include "Calculator.cpp"
#endif
Calculator.cpp
#include <iostream>
using namespace std;
#include "Calculator.h"
template <class TYPE>
Calculator<TYPE>::Calculator()
{
}
template <class TYPE>
TYPE Calculator<TYPE>::Sum(TYPE param1, TYPE param2){
cout << "Calculator::sum" << endl;
cout << param1 <<endl;
cout << param2 <<endl;
TYPE result = param1 + param2 ;
return result;
}
Main.cpp
#include <iostream>
using namespace std;
#include "Calculator.h"
int main(int argc, const char * argv[]) {
cout << "Hello, Calculator!\n";
Calculator<int> cObj;
int out = cObj.Sum(2,3);
cout << "out : " << out << endl;
Calculator<string> cObjS;
string outS = cObjS.Sum("A", "B");
cout << "outS : " << outS << endl;
cout << "Bye, Calculator!\n";
return 0;
}
Additionally, you can refer to the post, to know about how to keep the template source and header contents, and knowing about how to fix the compilation and linker issues (with reasons).

is it possible to override the c++ operator<< for a struct in a header file?

I am trying to print out the fields in a struct by overriding operator<<. This works fine if I place the override in a cpp file, however I would like to have it in my header file.
However when I do, I get the error:
multiple definition of `operator<<(std::basic_ostream<char, std::char_traits<char> >&, test)'
Is it possible to have in the header file?
test.h
#ifndef TEST_H
#define TEST_H
struct test{
int a;
int b;
int c;
};
std::ostream& operator<< (std::ostream& o, const test& t){
o <<"{ " << t.a << " }" << endl;
return o;
}
#endif
As with any function, if you define it in a header, make it inline:
inline std::ostream& operator<< (std::ostream& o, const test& t)
^^^^^^
This relaxes the One Definition Rule, allowing a definition in any translation unit that includes the header.

Where to put overload<< code?

I am trying to overload the stream operator <<, for a class Foo which has already a toString() function returning a string, with the following code:
std::ostream &operator<<( std::ostream &flux, Foo const& foo )
{
flux << foo.toString();
return flux;
}
In order to use it in a main.cppfile
My question is: Where to put that piece of code?
If I place it in the main.cpp, before its usage, it works well, but i may want to use it in other files.
If I place it in foo.cpp, I get a 'no such function' error:
src/main.cpp:77: error: no match for ‘operator<<’ in ‘std::cout << foo’
which make sense since the code is not included to the main.cpp file
If I place it in the foo.hclass header, outside class declaration, I get a 'multiple definition' error:
foo.o: In function `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Foo const&)':
foo.cpp:(.text+0x0): multiple definition of `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Matrix const&)'
bar.o:bar.cpp:(.text+0x0): first defined here
The foo.h header is indeed included in different classes/files, but there is a ifdef guard, so I don't understand this.
So How should I do?
There are multiple options:
Declare it in the header, after Foo, and define it in Foo.cpp.
//foo.h
class Foo
{};
std::ostream &operator<<( std::ostream &s, Foo const& foo );
//foo.cpp
#include "foo.h"
std::ostream &operator<<( std::ostream &s, Foo const& foo )
{
return s;
}
Define it as a friend inside the class definition.
//Foo.h
class Foo
{
friend std::ostream &operator<<( std::ostream &s, Foo const& foo )
{
return s;
}
};
Define it in the header, outside the class definition, and mark it as inline to prevent the multiple definition.
//Foo.h
class Foo
{
};
inline std::ostream &operator<<( std::ostream &s, Foo const& foo )
{
return s;
}
Put the prototype of the overload by the class declaration, the implementation thereof at the Foo implementation (or if you want it inline, put it at the Foo declaration).
So either:
// foo.h
#ifndef FOO_H_ASDSADKJSLADJL
#define FOO_H_ASDSADKJSLADJL
class Foo {
};
std::ostream& operator<< (std::ostream &, Foo const &);
#endif // FOO_H_ASDSADKJSLADJL
// foo.cpp
#include "foo.h"
....
std::ostream& operator<< (std::ostream &os, Foo const &) {
....
return os;
}
or
#ifndef FOO_H_ASDSADKJSLADJL
#define FOO_H_ASDSADKJSLADJL
class Foo {
};
inline std::ostream& operator<< (std::ostream &os, Foo const &) {
....
return os;
}
#endif // FOO_H_ASDSADKJSLADJL
Your error of the compiler not finding it was the lack of a prototype of your overload.
Put the declaration in the header file, and the definition in the cpp file.
That is, put
std::ostream &operator<<( std::ostream &flux, Foo const& foo );
in your header file, and put
std::ostream &operator<<( std::ostream &flux, Foo const& foo )
{
flux << foo.toString();
return flux;
}
in your cpp file.
This way, you can include the header file wherever you want, and things can use the function, but it will only be defined once, so you won't get the multiple definitions error.
Declare it in the header, where you declare Foo, define it in the source, where you define Foo methods.
As ususal with C and C++, you should
put the actual code into the appropriate .c / .cpp file - here I would recommend foo.cpp
put a predeclaration into the appropriate .h/.hpp header file, with an appropriate #ifdef guard for everything that is used from outside the main c/cpp file.
In some situations, you can use a #define macro, or an inline function. This should then be done in the header; there shouldn't be a multiple declaration error because of the inlining.
Technically you can do a lot of things. I recommend sticking to the best practise of defining the API in the header file, and putting the implementation into the code file. This is most extensible. The inline hack will work for this case, but if you at some later point decides to enhance the method and remove the inline, it will surprisingly break.
The header / code split is least likely to break.

Class template linker error

I've been trying to create a class cartesian which objects are 2 points on the a cartesian point (int or double). Then I want to overload <<. I get the error message :
Undefined symbols for architecture x86_64:
"cartesian<double, int>::cartesian(double, int)", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I dont understand where is My mistake.
THE HEADER
#include <iostream>
using namespace std;
template <class first, class second>
class cartesian
{
public:
cartesian(first, second);
//double getslope(cartesian &obj1, cartesian &obj2);
friend ostream& operator<< (ostream &out, cartesian &cPoint);
private:
first x;
second y;
};
THE CPP file
#include "cartesian.h"
#include <iostream>
using namespace std;
template<class first,class second>
cartesian<first, second>::cartesian(first a, second b)
:x(a), y(b)
{}
/*
// between obj1 and obj2
template<class first,class second>
double cartesian<first, second>::getslope(cartesian &obj1, cartesian &obj2){
return ((obj2.y-obj1.y)/(obj2.x-obj1.y));
}
*/
template<class first,class second>
ostream& operator<< (ostream &out,const cartesian<first, second> &cPoint)
{
// Since operator<< is a friend of the Point class, we can access
// Point's members directly.
out << "(" << cPoint.x << ", " <<
cPoint.y << ")";
return out;
}
THE MAIN
#include <iostream>
#include "cartesian.h"
using namespace std;
int main()
{
cartesian<double, int> ob11(3.4, 6);
return 0;
}
You need to put the implementation in the header file or in a file included by the header. The compiler needs access to the code in order to "build" the cartesian<double, int> specialization you require in main.
For example, here we put the constructor's implementation in the class declaration:
template <class first, class second>
class cartesian
{
public:
cartesian(first, second) :x(a), y(b) {}
};
It doesn't have to go inside the class declaration itself, but the code must be accessible from the header file.