operator<< overloading to call a print function trouble - c++

Okay I'm a little stuck on trying to overload the << operator for my template class. The requirement is that the << operator must call a void print function defined for this class.
Here is the important stuff from the template header:
template <class T>
class MyTemp {
public:
MyTemp(); //constructor
friend std::ostream& operator<< (std::ostream& os, const MyTemp<T>& a);
void print(std::ostream& os, char ofc = ' ') const;
and here is my print function basically it's a vector and prints last element to first:
template <class T>
void Stack<T>::print(std::ostream& os, char ofc = ' ') const
{
for ( int i = (fixstack.size()-1); i >= 0 ; --i)
{
os << fixstack[i] << ofc;
}
}
and here is how I have the operator<< overloaded:
template <class T>
std::ostream& operator<< (std::ostream& os, const Stack<T>& a)
{
// So here I need to call the a.print() function
}
But I am receiving an "unresolved external symbol" error. So really I guess I have two issues. The first, is the way to fix the error above. Second, once that is fixed would I just call a.print(os) inside << overload? I know it needs to return an ostream though. Any help would be greatly appreciated!

The simplest thing to do would be to leave print public (as it is in your example), so the operator doesn't need to be a friend.
template <class T>
class MyTemp {
public:
void print(std::ostream& os, char ofc = ' ') const;
};
template <class T>
std::ostream& operator<< (std::ostream& os, const MyTemp<T>& a) {
a.print(os);
return os;
}
If you do need it to be private, then you need to declare the correct template specialisation to be a friend - your friend declaration declares a non-template operator in the surrounding namespace, not a template. Unfortunately, to make a template a friend you need to declare it beforehand:
// Declare the templates first
template <class T> class MyTemp;
template <class T> std::ostream& operator<< (std::ostream&, const MyTemp<T>&);
template <class T>
class MyTemp {
public:
friend std::ostream& operator<< <>(std::ostream& os, const MyTemp<T>& a);
// With a template thingy here ^^
private:
void print(std::ostream& os, char ofc = ' ') const;
};
template <class T>
std::ostream& operator<< (std::ostream& os, const MyTemp<T>& a) {
a.print(os);
return os;
}
Or you could define the operator inline:
template <class T>
class MyTemp {
public:
friend std::ostream& operator<<(std::ostream& os, const MyTemp<T>& a) {
a.print(os);
return os;
}
private:
void print(std::ostream& os, char ofc = ' ') const;
};
For your last question:
Second, once that is fixed would I just call a.print(os) inside << overload? I know it needs to return an ostream though.
It does indeed need to return an ostream - so just return the one that was passed in, as in my example code.

This error means there is an symbol which could not be recognized by the linker.on what variable are u getting this error
and also please check on stack as well because there is a std::stack class available.

As your print member function is public, there's no need to declare operator<< as friend.
Beware that you are using class Stack is your overload, and MyTemp above ...

Related

How to properly overload the insertion operator for a templated class that's part of a user-defined namespace?

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

Friend template overloaded operator <<: unresolved external symbol

I'm having issues with the error
Error LNK2019 unresolved external symbol "class std::basic_ostream > & __cdecl cop4530::operator<<(class std::basic_ostream > &,class rob::Stack const &)" (??6rob##YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV12#ABV?$Stack#H#0##Z) referenced in function _main Project7 c:\Users\Robrik\documents\visual studio 2015\Projects\Project7\Project7\post.obj 1
Right now, all that post is doing is calling the operator<<
The declaration
namespace rob {
template < typename T> class Stack {
friend std::ostream& operator<< (std::ostream& os, const Stack<T>& a);
void print(std::ostream& os, char ofc = ' ') const;
private:
std::vector<T> arr;
};
The definition
template < typename T>
inline std::ostream & rob::operator<<(std::ostream & os, const Stack<T>& a) {
return a.print(os, ' ');
}
template<typename T>
inline void rob::Stack<T>::print(std::ostream & os, char c) const
{
for (int i = 0; i != arr.size(); i++)
{
os << c << arr[i];
}
os << '\n';
}
They are located in a .h file and a .hpp respectively, I require that the operator is not a member function (for assignment).
The issue with the code sample;
template <typename T>
class Stack {
friend std::ostream& operator<< (std::ostream& os, const Stack<T>& a);
void print(std::ostream& os, char ofc = ' ') const;
// ...
};
Is that the operator<< is being declared as a non-template function. For every type T used with Stack, there needs to be a non-template operator<<. For example, if there is a type Stack<int> declared, then there must be an operator implementation as follows;
std::ostream& operator<< (std::ostream& os, const Stack<int>& a) {/*...*/}
Since it is not implemented, the linker fails to find it and results in the error you get.
As a side note; gcc warns about this as follows
warning: friend declaration 'std::ostream& operator<<(...)' declares a non-template function [-Wnon-template-friend]
note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
This is probably not what is intended, that every instantiation has its own implementation.
To correct this, you can declare a template operator before the Stack type and then declare as a friend, an instantiation. The syntax looks a little awkward, but is looks as follows;
// forward declare the Stack
template <typename>
class Stack;
// forward declare the operator <<
template <typename T>
std::ostream& operator<<(std::ostream&, const Stack<T>&);
template <typename T>
class Stack {
friend std::ostream& operator<< <>(std::ostream& os, const Stack<T>& a);
// note the required <> ^^^^
void print(std::ostream& os, char ofc = ' ') const;
// ...
};
template <typename T>
std::ostream& operator<<(std::ostream&, const Stack<T>&)
{
// ... implement the operator
}
The above code limits the friendship of the operator to the corresponding instantiation of Stack, i.e. the operator<< <int> instantiation is limited to access the private members of the instantiation of Stack<int>.
Alternatives include allowing the friendship to extend to all instantiations of the templates;
template <typename T>
class Stack {
template <typename T1>
friend std::ostream& operator<<(std::ostream& os, const Stack<T1>& a);
// ...
};
The implementation for the operator<< could then be done inline inside the class definition, or outside.
You should as well declare function signature inside rob namespace which it actually belongs:
namespace rob {
template <typename T>
class Stack {
friend std::ostream& operator<< (std::ostream& os, const Stack<T>& a);
};
template < typename T>
std::ostream& operator<< (std::ostream& os, const Stack<T>& a){
...
}
In addition to #LibertyPaul's answer you need to add a template<T> to friend std::os... line, in order to work:
namespace rob {
template <typename T> class Stack {
friend std::ostream& operator<< (std::ostream& os, const Stack<T>& a) {
return a.arr.print(os, ' ');
}
};
}

Templates and overloadering operator << [duplicate]

This question already has answers here:
Overloading friend operator << for template class [duplicate]
(3 answers)
Closed 7 years ago.
I'm trying to overload the << operator for a class template, but the compiler gives me a linker error. The goal is to be able to send a de-referenced base class pointer to std::cout so that the derived operator<< gets called.
Is this possible?
class IBase
{
public:
IBase() {};
virtual ~IBase() {};
};
template <typename T>
class Derived
: public IBase
{
public:
Derived(T data);
friend std::ostream& operator<<(std::ostream& os, const Derived<T>& dt);
private:
T data_;
};
template <typename T>
Derived<T>::Derived(T data)
: IBase(),
data_(data)
{
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const Derived<T>& dt)
{
os << dt.data_;
return os;
}
int _tmain(int argc, _TCHAR* argv[])
{
// Question 1
Derived<int> der(234);
std::cout << der;
// Question 2
//IBase* base = new Derived<int>(5);
// std::cout << *base
}
Here are the errors:
error LNK2001: unresolved external symbol "class
std::basic_ostream > & __cdecl
operator<<(class std::basic_ostream
&,class Derived const &)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#ABV?$Derived#H###Z)
and
fatal error LNK1120: 1 unresolved externals
You need to declarate friend operator as a template too
template<typename T1>
friend std::ostream& operator<<(std::ostream& os, const Derived<T1>& dt);
friend std::ostream& operator<<(std::ostream& os, const Derived<T>& dt);
declares a non template version friend, so you would have to implement
std::ostream& operator<<(std::ostream& os, const Derived<T>& dt);
for every T you use:
std::ostream& operator<<(std::ostream& os, const Derived<int>& dt) {
return os << dt.data_;
}
And so on.
A way to do it without duplicate code is with definition inside the class:
template <typename T>
class Derived : public IBase
{
public:
explicit Derived(T data);
friend std::ostream& operator<<(std::ostream& os, const Derived<T>& dt)
{
return os << dt.data_;
}
private:
T data_;
};
Demo
An other alternative is to make the function template.
// Forward declarations
template <typename T> class Derived;
template <typename T> std::ostream& operator<<(std::ostream& os, const Derived<T>& dt);
And then in Derived, you have 2 choices:
Declare each the template method friend:
template <typename T2>
friend std::ostream& operator<<(std::ostream& os, const Derived<T2>& dt);
So std::ostream& operator<<(std::ostream& os, const Derived<int>& dt) has access to private members of Derived<int>, but also to the ones of Derived<char>
Demo
Declare only the template which matches the argument:
friend std::ostream& operator<< <>(std::ostream& os, const Derived& dt);
and so std::ostream& operator<<(std::ostream& os, const Derived<int>& dt) doesn't have access to private members of Derived<char>.
Demo
replace
friend std::ostream& operator<<(std::ostream& os, const Derived<T>& dt);
with
template<typename D>
friend std::ostream& operator<<(std::ostream& os, const Derived<D>& dt);
Your immediate problem is that the operator needs to be templated.
However, your ultimate goal can't be attained through templates alone as dereferencing a IBase* gets you a IBase& - template instantiation occurs at compile time and the compiler has no access to the runtime type.
So your templated operator will never be used if you pass a dereferenced IBase* to operator <<.
Instead, add a virtual output function to the base and override it:
class IBase
{
public:
IBase() {};
virtual ~IBase() {};
virtual std::ostream& output(std::ostream&) const = 0;
};
template <typename T>
class Derived
: public IBase
{
public:
Derived(T data);
virtual std::ostream& output(std::ostream& os) const
{
os << data;
return os;
}
private:
T data_;
};
std::ostream& operator<<(std::ostream& os, const IBase& dt)
{
return dt.output(os);
}
You don't need to make your friend a template:
friend std::ostream& operator<<(std::ostream& os, const Derived<T>& dt);
This needs to be changed to:
friend std::ostream& operator<< <>(std::ostream& os, const Derived<T>& dt);
The operator<< function will need to be visible before the friend declaration for this form to work.
You should prefer this form to making the friend a template because you don't need all of the operator's instantiations to be friends, just one of them.

error when trying to overload << operator and using friend function

I am trying to overload << operator and using friend function.
Below code chunk works just fine.
template <class T>
class Mystack{
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
d.print(s);
return s;
}
};
Since it is friend function I would obviously want to define it outside the class without using scope resolution operator. But when I try that I get error.
template <class T>
class Mystack{
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d);
};
template <class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
d.print(s);
return s;
}
Below is the code snippet for main
Mystack<int> intstack;
std::cout << intstack;
ERROR : Unresolved extrernal symbol.
P.S: Its not the complete running code. Just a sample. Kindly bear.
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d);
declares and befriends a non-template operator<< function. So Mystack<int> would have as its friend a non-template function std::ostream& operator<<(std::ostream& s, Mystack<int> const& d);, etc.
template<class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
d.print(s);
return s;
}
defines an operator<< function template.
The two are not the same. When you write std::cout << intstack;, the overload resolution rules resolve it to the non-template operator<< function you declared, but it isn't defined, so you get a linker error.
There's no way to define a non-template function for every instantiation of a class template outside the class template. You can, however, befriend a specialization of your operator<< function template:
// forward declarations
template <class T>
class Mystack;
template <class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d);
template <class T>
class Mystack
{
friend std::ostream& operator<< <T>(std::ostream& s, Mystack<T> const& d);
// ^^^
};
or befriend every specialization of the function template, which is worse from an encapsulation point of view (since, e.g., operator<< <int> would be a friend of Mystack<float>):
template <class T>
class Mystack
{
public:
template <class U>
friend std::ostream& operator<<(std::ostream& s, Mystack<U> const& d);
};
or just define the friend function inside the class.

Using overloaded output operator for templated class: Undefined symbols for architecture x86_64 [duplicate]

I am trying to overload << operator and using friend function.
Below code chunk works just fine.
template <class T>
class Mystack{
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
d.print(s);
return s;
}
};
Since it is friend function I would obviously want to define it outside the class without using scope resolution operator. But when I try that I get error.
template <class T>
class Mystack{
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d);
};
template <class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
d.print(s);
return s;
}
Below is the code snippet for main
Mystack<int> intstack;
std::cout << intstack;
ERROR : Unresolved extrernal symbol.
P.S: Its not the complete running code. Just a sample. Kindly bear.
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d);
declares and befriends a non-template operator<< function. So Mystack<int> would have as its friend a non-template function std::ostream& operator<<(std::ostream& s, Mystack<int> const& d);, etc.
template<class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
d.print(s);
return s;
}
defines an operator<< function template.
The two are not the same. When you write std::cout << intstack;, the overload resolution rules resolve it to the non-template operator<< function you declared, but it isn't defined, so you get a linker error.
There's no way to define a non-template function for every instantiation of a class template outside the class template. You can, however, befriend a specialization of your operator<< function template:
// forward declarations
template <class T>
class Mystack;
template <class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d);
template <class T>
class Mystack
{
friend std::ostream& operator<< <T>(std::ostream& s, Mystack<T> const& d);
// ^^^
};
or befriend every specialization of the function template, which is worse from an encapsulation point of view (since, e.g., operator<< <int> would be a friend of Mystack<float>):
template <class T>
class Mystack
{
public:
template <class U>
friend std::ostream& operator<<(std::ostream& s, Mystack<U> const& d);
};
or just define the friend function inside the class.