I am trying to overload operator<< in my code. If I comment out the lines where I try to use the << operator with my custom class, it compiles fine. The error almost looks like it doesn't like the c++ libraries (?).
All my research on this problem has stated that it is a linking problem. Most suggest using g++ instead of gcc. I am using g++ as my compiler, and I get this error still.
Code:
#include <iostream>
using namespace std;
//prototype the class and the functions
template<class T> class strange;
template<class T> ostream& operator<< (ostream& osObject, strange<T>& sObject);
//begin class
template <class T>
class strange
{
public:
// .... function prototypes go here.
strange(T x,T y);
friend ostream& operator<< <> (ostream& osObject, strange<T>& sObject);
private:
T a;
T b;
};
// .... your function definitions go here
template <class T>
strange<T>::strange(T first, T second){
a = first;
b = second;
}
template <class T>
ostream& operator<< (ostream& osObject, const strange<T>& sObject){
osObject << sObject.a << ", " << sObject.b;
return osObject;
}
int main()
{
strange<int> x1(4,6) , x2(12,2) ;
//strange<char> y1('m','n') , y2('m','n') ;
cout << "x1 = " << x1 << endl;
return 0;
}
Error:
test.cpp:(.text+0x7a): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& operator<< <int>(std::basic_ostream<char, std::char_traits<char> >&, strange<int>&)'
collect2: ld returned 1 exit status
Any idea what is causing this?
I made two changes, one to the friend definition, and one to the prototype. This should compile:
#include <iostream>
using namespace std;
//prototype the class and the functions
template<class T> class strange;
template<class T> ostream& operator<< (ostream& osObject, const strange<T>& sObject);
//begin class
template <class T>
class strange
{
public:
// .... function prototypes go here.
strange(T x,T y);
friend ostream& operator<< <> (ostream& osObject, const strange<T>& sObject);
private:
T a;
T b;
};
// .... your function definitions go here
template <class T>
strange<T>::strange(T first, T second){
a = first;
b = second;
}
template <class T>
ostream& operator<< (ostream& osObject, const strange<T>& sObject){
osObject << sObject.a << ", " << sObject.b;
return osObject;
}
int main()
{
strange<int> x1(4,6) , x2(12,2) ;
//strange<char> y1('m','n') , y2('m','n') ;
cout << "x1 = " << x1 << endl;
return 0;
}
And this compiles in clang, g++ and at ideone
To explain the issue, the compiler is looking at link time for a definition for:
std::ostream & operator<< <int>(std::ostream &, strange<int>&);
When you only have a definition for:
std::ostream & operator<< <int>(std::ostream &, strange<int> const &);
This is because of the miscommunication between your prototypes (both the explicit one and the friend) and your definition.
Related
I am reading Section 2.4 of the book "C++ tempalte, a complete guide".
I tried to override output operator (<<) as a function template outside the class template Stack<>.
Below is my code, but it doesn't work.
#include <iostream>
#include <string>
#include <vector>
template<class T>
class Stack
{
private:
std::vector<T> v;
public:
void push(T a);
void printOn(std::ostream & os) const;
template <typename U>
friend std::ostream& operator<< (std::ostream& out, const Stack<U> & s);
};
template<typename T>
std::ostream& operator<< (std::ostream out, const Stack<T> & s)
{
s.printOn(out);
return out;
}
template<class T>
void Stack<T>::push(T a)
{
v.push_back(a);
}
template<class T>
void Stack<T>::printOn(std::ostream & out) const
{
for(T const & vi : v)
{out << vi << " ";}
}
int main()
{
Stack<int> s1;
s1.push(12);
s1.push(34);
std::cout << s1;
}
You are just omitting the &, which makes the operator<< inside and outside the class have different function signatures, they are both valid for std::cout << s1, hence the ambiguity
template<typename T>
std::ostream& operator<< (std::ostream& out, const Stack<T> & s)
// ^
{
s.printOn(out);
return out;
}
I have read couple of the questions regarding my problem on StackOverflow.com now, and none of it seems to solve my problem. Or I maybe have done it wrong...
The overloaded << works if I make it into an inline function. But how do I make it work in my case?
warning: friend declaration std::ostream& operator<<(std::ostream&, const D<classT>&)' declares a non-template function
warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning
/tmp/cc6VTWdv.o:uppgift4.cc:(.text+0x180): undefined reference to operator<<(std::basic_ostream<char, std::char_traits<char> >&, D<int> const&)'
collect2: ld returned 1 exit status
The code:
template <class T>
T my_max(T a, T b)
{
if(a > b)
return a;
else
return b;
}
template <class classT>
class D
{
public:
D(classT in)
: d(in) {};
bool operator>(const D& rhs) const;
classT operator=(const D<classT>& rhs);
friend ostream& operator<< (ostream & os, const D<classT>& rhs);
private:
classT d;
};
int main()
{
int i1 = 1;
int i2 = 2;
D<int> d1(i1);
D<int> d2(i2);
cout << my_max(d1,d2) << endl;
return 0;
}
template <class classT>
ostream& operator<<(ostream &os, const D<classT>& rhs)
{
os << rhs.d;
return os;
}
This is one of those frequently asked questions that have different approaches that are similar but not really the same. The three approaches differ in who you are declaring to be a friend of your function --and then on how you implement it.
The extrovert
Declare all instantiations of the template as friends. This is what you have accepted as answer, and also what most of the other answers propose. In this approach you are needlessly opening your particular instantiation D<T> by declaring friends all operator<< instantiations. That is, std::ostream& operator<<( std::ostream &, const D<int>& ) has access to all internals of D<double>.
template <typename T>
class Test {
template <typename U> // all instantiations of this template are my friends
friend std::ostream& operator<<( std::ostream&, const Test<U>& );
};
template <typename T>
std::ostream& operator<<( std::ostream& o, const Test<T>& ) {
// Can access all Test<int>, Test<double>... regardless of what T is
}
The introverts
Only declare a particular instantiation of the insertion operator as a friend. D<int> may like the insertion operator when applied to itself, but it does not want anything to do with std::ostream& operator<<( std::ostream&, const D<double>& ).
This can be done in two ways, the simple way being as #Emery Berger proposed, which is inlining the operator --which is also a good idea for other reasons:
template <typename T>
class Test {
friend std::ostream& operator<<( std::ostream& o, const Test& t ) {
// can access the enclosing Test. If T is int, it cannot access Test<double>
}
};
In this first version, you are not creating a templated operator<<, but rather a non-templated function for each instantiation of the Test template. Again, the difference is subtle but this is basically equivalent to manually adding: std::ostream& operator<<( std::ostream&, const Test<int>& ) when you instantiate Test<int>, and another similar overload when you instantiate Test with double, or with any other type.
The third version is more cumbersome. Without inlining the code, and with the use of a template, you can declare a single instantiation of the template a friend of your class, without opening yourself to all other instantiations:
// Forward declare both templates:
template <typename T> class Test;
template <typename T> std::ostream& operator<<( std::ostream&, const Test<T>& );
// Declare the actual templates:
template <typename T>
class Test {
friend std::ostream& operator<< <T>( std::ostream&, const Test<T>& );
};
// Implement the operator
template <typename T>
std::ostream& operator<<( std::ostream& o, const Test<T>& t ) {
// Can only access Test<T> for the same T as is instantiating, that is:
// if T is int, this template cannot access Test<double>, Test<char> ...
}
Taking advantage of the extrovert
The subtle difference between this third option and the first is in how much you are opening to other classes. An example of abuse in the extrovert version would be someone that wants to get access into your internals and does this:
namespace hacker {
struct unique {}; // Create a new unique type to avoid breaking ODR
template <>
std::ostream& operator<< <unique>( std::ostream&, const Test<unique>& )
{
// if Test<T> is an extrovert, I can access and modify *any* Test<T>!!!
// if Test<T> is an introvert, then I can only mess up with Test<unique>
// which is just not so much fun...
}
}
You can't declare a friend like that, you need to specify a different template type for it.
template <typename SclassT>
friend ostream& operator<< (ostream & os, const D<SclassT>& rhs);
note SclassT so that it doesn't shadow classT. When defining
template <typename SclassT>
ostream& operator<< (ostream & os, const D<SclassT>& rhs)
{
// body..
}
This worked for me without any compiler warnings.
#include <iostream>
using namespace std;
template <class T>
T my_max(T a, T b)
{
if(a > b)
return a;
else
return b;
}
template <class classT>
class D
{
public:
D(classT in)
: d(in) {};
bool operator>(const D& rhs) const {
return (d > rhs.d);
}
classT operator=(const D<classT>& rhs);
friend ostream& operator<< (ostream & os, const D& rhs) {
os << rhs.d;
return os;
}
private:
classT d;
};
int main()
{
int i1 = 1;
int i2 = 2;
D<int> d1(i1);
D<int> d2(i2);
cout << my_max(d1,d2) << endl;
return 0;
}
I think you shouldn't make friend in the first place.
You can create a public method call print, something like this (for a non template class):
std::ostream& MyClass::print(std::ostream& os) const
{
os << "Private One" << privateOne_ << endl;
os << "Private Two" << privateTwo_ << endl;
os.flush();
return os;
}
and then, outside the class (but in the same namespace)
std::ostream& operator<<(std::ostream& os, const MyClass& myClass)
{
return myClass.print(os);
}
I think it should work also for template class, but I haven't tested yet.
Here you go:
#include <cstdlib>
#include <iostream>
using namespace std;
template <class T>
T my_max(T a, T b)
{
if(a > b)
return a;
else
return b;
}
template <class classT>
class D
{
public:
D(classT in)
: d(in) {};
bool operator>(const D& rhs) const { return d > rhs.d;};
classT operator=(const D<classT>& rhs);
template<class classT> friend ostream& operator<< (ostream & os, const D<classT>& rhs);
private:
classT d;
};
template<class classT> ostream& operator<<(ostream& os, class D<typename classT> const& rhs)
{
os << rhs.d;
return os;
}
int main()
{
int i1 = 1;
int i2 = 2;
D<int> d1(i1);
D<int> d2(i2);
cout << my_max(d1,d2) << endl;
return 0;
}
I checked the answers to this question: Overloading operator<< for a templated class, but unfortunately nothing is working for me so far. Meaning, the compiler is constantly throwing myriad errors at me.
#include <iostream>
namespace usr {
// Forward declarations
template <typename T> class A;
template <typename T>
std::ostream& operator<<(std::ostream& os, const usr::A<T>&);
template <typename T>
class A {
public:
friend std::ostream& operator<<(std::ostream& os,
const usr::A<T>& a);
};
template <typename T>
std::ostream& operator<<(std::ostream& os, const usr::A<T>& a) {
os << "test";
return os;
}
}
int main() {
usr::A<int> a;
std::cout << a << std::endl;
return 0;
}
The error I get:
$ g++ -std=c++11 test.cpp && ./a.out
test.cpp:15:67: warning: friend declaration ‘std::ostream& usr::operator<<(std::ostream&, const usr::A<T>&)’ declares a non-template function [-Wnon-template-friend]
const usr::A<T>& a);
^
test.cpp:15:67: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
/tmp/ccklebu2.o: In function `main':
test.cpp:(.text+0x24): undefined reference to `usr::operator<<(std::ostream&, usr::A<int> const&)'
collect2: error: ld returned 1 exit status
The following version doesn't not work either:
#include <iostream>
namespace usr {
template <typename T>
class A {
public:
friend std::ostream& operator<<(std::ostream& os, const usr::A& a) {
os << "test";
return os;
}
};
}
int main() {
usr::A<int> a;
std::cout << a << std::endl;
return 0;
}
Here's the error I get plus a whole lot more which I'm not going to include here:
test2.cpp:8:55: error: invalid use of template-name ‘usr::A’ without an argument list
const usr::A& a) {
You need to take ostream in your function by reference. Also, when you declare a friend you need to include the template argument: friend std::ostream& operator<< <T>. Here's your first version modified that works for me:
#include <iostream>
namespace usr {
// Forward declarations
template <typename T> class A;
template <typename T>
std::ostream& operator<<(std::ostream& os, const usr::A<T>&);
// Class
template <typename T>
class A {
public:
friend std::ostream& operator<< <T>(std::ostream& os, const usr::A<T>& a);
};
// Friend function
template <typename T>
std::ostream& operator<<(std::ostream& os, const usr::A<T>& a) {
os << "test";
return os;
}
}
int main() {
usr::A<int> a;
std::cout << a << std::endl;
return 0;
}
The first answer to your referred to question would seem to answer this.
In the first case, you need the friend delcaration to declare a friend template rather than non-template overloaded functions:
friend std::ostream& operator<< <>(std::ostream &os, const usr::A<T>& a);
note the extra <> that designates this as a firend template.
In the second case, you need to prived the template argument to the friend function:
friend std::ostream& operator<<(std::ostream &os, const usr::A<T>& a) {
note the extra <T>, the type parameter to A
I have written a code:
#include <iostream>
#include <cassert>
using namespace std;
template<typename T>
class dynArray{
int size;
T* ptr;
public:
dynArray(int n=0);
~dynArray();
T& operator[] (const int index);
friend ostream& operator<<<T>(ostream& os,const dynArray<T>& A);
};
template<typename T> dynArray<T>::dynArray(int n):size(n){
if (size==0)
{
cout << "Size Zero"<< endl;
ptr=NULL;}
else
{
try{
ptr = new T[size];
cout << "Constructor Called" << endl;
}
catch(bad_alloc xa)
{
cout << "Allocation Failure" <<endl;
exit(EXIT_FAILURE);
}
}
}
template<typename T> dynArray<T>::~dynArray(){
cout << "Destructor Called for array of size : " << size << endl;
delete[] ptr;
}
template<typename T> T& dynArray<T>::operator[] (const int index){
assert(index >=0 && index <size);
return *(ptr+index);
}
template<typename T> ostream& operator<< <T>(ostream& os,const dynArray<T>& A){
for (int i=0; i < A.size ; i++)
os << *(A.ptr+i) << " ";
return os;
}
int main()
{
dynArray<int> array1;
dynArray<int> array2(5);
array2[0]=15;
array2[3]= 45;
cout << array2 << endl;
return 0;
}
But while compiling getting error:
$ g++ -Wall DynArray.cpp -o DynArray
DynArray.cpp:46: error: partial specialization `operator<< <T>' of function template
DynArray.cpp: In instantiation of `dynArray<int>':
DynArray.cpp:54: instantiated from here
DynArray.cpp:14: error: template-id `operator<< <int>' for `std::basic_ostream<char, std::char_traits<char> >& operator<<(std::basic_ostream<char, std::char_traits<char> >&, const dynArray<int>&)' does not match any template declaration
DynArray.cpp: In function `std::ostream& operator<<(std::ostream&, const dynArray<T>&) [with T = int]':
DynArray.cpp:61: instantiated from here
DynArray.cpp:8: error: `int dynArray<int>::size' is private
DynArray.cpp:47: error: within this context
DynArray.cpp:9: error: `int*dynArray<int>::ptr' is private
DynArray.cpp:48: error: within this context
I think my template syntax is wrong for operator<<. Can any one help please? Not able to figure out where is the mistake.
You cannot friend a specialization of an undeclared template function. You need to declare the operator << beforehand. Of course to do so, you'll need to already have a declaration of dynArray. This mess of forward declarations looks like this (Live at Coliru):
template<typename T> class dynArray;
template<typename T>
ostream& operator << (ostream& os, const dynArray<T>& A);
template<typename T>
class dynArray {
// ...
friend ostream& operator<< <T>(ostream& os, const dynArray& A);
};
As #ooga points out in his comment, the template parameters in the friend declaration are unnecessary; the compiler can deduce them. You could simply declare it as:
friend ostream& operator<< <> (ostream& os, const dynArray& A);
I personally find that syntax a bit punctuation-heavy in this instance.
Alternatively, if you find the forward declarations offensive, you could declare a separate non-template friend function for each specialization of dynArray by defining it in the class definition (Coliru again):
template<typename T>
class dynArray {
// ...
friend ostream& operator<< (ostream& os,const dynArray& A) {
for (int i=0; i < A.size ; i++)
os << *(A.ptr+i) << " ";
return os;
}
};
In the class declare friend as :-
template<typename U>
friend ostream& operator<<(ostream& os,const dynArray<U>& A);
And define it as :-
template<typename U>
ostream& operator<< (ostream& os,const dynArray<U>& A){...}
See HERE
template <>
class test<int> {
int y;
public:
test(int k) : y(k) {}
friend ofstream& operator<< <test<int>> (ofstream& os, const test<int>& t);
};
template<>
ofstream& operator<< <test<int> > (ofstream& os, const test<int>& t)
{
os << t.y;
return os;
}
The code above is specialized template class of test in a int version. I am trying to overload ofstream operator<< function. But it shows error message;
C2027: use of undefined type 'std::basic_ofstream<_Elem,_Traits>'
Besides, the same method works on a ordinary function (not ofstream operator<< but the function that I make) Is there anyway to us operator<< function of ofstream in a specialized template class ?
You need to include
#include <iostream>
At the time of instantiation of the function template. Perhaps you only included
#include <iosfwd>
Besides, you shouldn't be defining (static) friend as a template: https://ideone.com/1HRlZ
#include <iostream>
template <typename> class test;
template <>
class test<int> {
int y;
public:
test(int k) : y(k) {}
friend std::ostream& operator<<(std::ostream& os, const test& t);
};
std::ostream& operator<< (std::ostream& os, const test<int>& t)
{
return os << t.y;
}
int main()
{
test<int> a(42);
std::cout << a << std::endl;
}
Note that it isn't a good idea to have 'using namespace std' in your header file, which is why I removed it from the sample. (It might cause conflicts for users of your header file when they include your header)
There are a number of interesting issues here. First the obvious housekeeping
You should #include <fstream> and don't forget using namespace std.
operator << shouldn't be a template, it should be an overloaded function.
os << t.y confuses the compiler for me (g++ 4.4.3: "warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:"). You intend to push the int to the stream obviously, but the compiler notices that an int can be turned into a test<int> via your constructor and therefore it doesn't know whether you want to push an int or a test<int>. This is stupid I know, and can be solved by making the constructor explicit.
#include <fstream>
using namespace std;
template <typename T>
class test;
template <>
class test<int> {
int y;
public:
explicit test(int k) : y(k) {}
// friend ofstream& operator<< < test<int> > (ofstream& os, const test<int>& t);
friend ofstream& operator<< (ofstream& os, const test<int>& t);
};
// template<>
// ofstream& operator<< <test<int> > (ofstream& os, const test<int>& t)
ofstream& operator<< (ofstream& os, const test<int>& t)
{
os << t.y;
return os;
}
int main() {
}