I can't figure out the correct syntax for templated friend overloaded operators. Using the code (I'm only showing the relevant stuff) from the class header (please don't tell me to change anything from this section):
#include <iostream>
using namespace std;
template <typename T>
class List;
template <typename T>
class Queue;
template <typename T>
class Stack;
template <typename T>
class Node{
private:
friend class List<T>;
friend class Stack<T>;
friend class Queue<T>;
friend ostream& operator<< <>(const ostream&, const List<T>&);
friend ostream& operator<< <>(const ostream&, const Stack<T>&);
friend ostream& operator<< <>(const ostream&, const Queue<T>&);
};
template <typename T>
class List{
public:
friend ostream& operator<< <>(const ostream&, const List<T>&);
};
template <typename T>
class Stack{
public:
friend ostream& operator<< <>(const ostream&, const Stack<T>&);
};
template <typename T>
class Queue{
public:
friend ostream& operator<< <>(const ostream&, const Queue<T>&);
};
This is where the implementation comes into play, and I can't figure out the syntax.
template <typename T>
ostream& operator<<(const ostream& cout, const List<T>& toPrint){ <-- what do I change here?
// irrelevant body
}
template <typename T>
ostream& operator<<(const ostream& cout, const Stack<T>& toPrint){ <-- what do I change here?
// irrelevant body
}
template <typename T>
ostream& operator<<(const ostream& cout, const Queue<T>& toPrint){ <-- what do I change here?
// irrelevant body
}
What do I need to change in each of those three lines to make this work?
I keep getting compiler errors:
error: template-id ‘operator<< <>’ for ‘std::ostream& operator<<(const ostream&, const Queue<Card>&)’ does not match any template declaration
I guess it might be those:
friend ostream& operator<< <>(const ostream&, const List<T>&);
friend ostream& operator<< <>(const ostream&, const Stack<T>&);
friend ostream& operator<< <>(const ostream&, const Queue<T>&);
lines. You didn't specify the type of a template:
friend ostream& operator<< <T>(ostream&, const List<T>&);
friend ostream& operator<< <T>(ostream&, const Stack<T>&);
friend ostream& operator<< <T>(ostream&, const Queue<T>&);
so compiler couldn't match declarations with definitions.
So declarations:
friend ostream& operator<< <T>(const ostream&, const List<T>&);
and definitions:
template <typename T>
ostream& operator<<(ostream& cout, const List<T>& toPrint) {
// irrelevant body
}
Also to prevent compiler from complaining about not declared templates add declarations before class definition.
Final results:
#include <iostream>
using namespace std;
// Class delcarations - we need them to declare functions
template <typename T>
class List;
template <typename T>
class Stack;
template <typename T>
class Queue;
// operator<< function declaration informs compiler that there is function that can be befriended
template <typename T>
ostream& operator<<(ostream&, const List<T>&);
template <typename T>
ostream& operator<<(ostream&, const Stack<T>&);
template <typename T>
ostream& operator<<(ostream&, const Queue<T>&);
// Class definitions
template <typename T>
class Node{
private:
friend class List<T>;
friend class Stack<T>;
friend class Queue<T>;
};
template <typename T>
class List{
public:
friend ostream& operator<< <T>(ostream&, const List<T>&);
};
template <typename T>
class Stack{
public:
friend ostream& operator<< <T>(ostream&, const Stack<T>&);
};
template <typename T>
class Queue{
public:
friend ostream& operator<< <T>(ostream&, const Queue<T>&);
};
// Actual implemetations
template <typename T>
ostream& operator<<(ostream& out, const List<T>& toPrint) {
out << "List";
return cout;
}
template <typename T>
ostream& operator<<(ostream& out, const Stack<T>& toPrint) {
out << "Stack";
return out;
}
template <typename T>
ostream& operator<<(ostream& out, const Queue<T>& toPrint) {
out << "Queue";
return out;
}
// Template instantations test
int main() {
List<int> list;
Stack<int> stack;
Queue<int> queue;
cout << list << endl
<< stack << endl
<< queue << endl;
return 0;
}
for me it printed:
List
Stack
Queue
Here and here you have some nice examples.
EDIT: You were right, I made some mistakes. Corrected the answer to the working one.
there are some weird things here.
firstly the error message renders ostream differently, the fact that it qualifies the return value as std::ostream& and not the parameter parsed in seems a bit fishy - but it could be a red herring.
it is always a shame to see "using namespace std;". i consider the using keyword to be absolutely forbidden - so i have no idea what problems or changes this might cause. i simply suspect it is related.
now - to debug this properly i'd suggest replacing the operator and friend with regular function templates and breaking the access levels to allow that test (i.e. remove private etc.), then introduce each element one at a time until you find which part is actually causing the problem.
Related
I tried to separate the declaration and definition of my templated member function of a templated class, but ended up with the following error and warning.
template <typename I>
class BigUnsigned{
const size_t cell_size=sizeof(I);
std::vector<I> _integers;
public:
BigUnsigned();
BigUnsigned(I);
friend std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu);
};
std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu){
for (auto integer : bu._integers){
out<<integer<<std::endl;
}
return out;
}
../hw06/bigunsigned.h:13:77: warning: friend declaration
'std::ostream& operator<<(std::ostream&, const BigUnsigned&)'
declares a non-template function [-Wnon-template-friend]
friend std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu);
^ ../hw06/bigunsigned.h:13:77: note: (if this is not what you
intended, make sure the function template has already been declared
and add <> after the function name here) ../hw06/bigunsigned.h:16:51:
error: invalid use of template-name 'BigUnsigned' without an argument
list std::ostream& operator<<(std::ostream& out, const BigUnsigned&
bu){
^ ../hw06/bigunsigned.h: In function 'std::ostream&
operator<<(std::ostream&, const int&)': ../hw06/bigunsigned.h:17:28:
error: request for member '_integers' in 'bu', which is of non-class
type 'const int'
for (auto integer : bu._integers){
^
When I joined the declaration and definition like this, everything compiles fine.
template <typename I>
class BigUnsigned{
const size_t cell_size=sizeof(I);
std::vector<I> _integers;
public:
BigUnsigned();
BigUnsigned(I);
friend std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu){
for (auto integer : bu._integers){
out<<integer<<std::endl;
}
return out;
}
};
The purpose was to print member variable _integers to cout. What might be the problem?
P.S.: Using this question I made the function free, but did not help.
BigUnsigned is a template type so
std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu)
Will not work as there is no BigUnsigned. You need to make the friend function a template so you can take different types of BigUnsigned<some_type>s.
template <typename I>
class BigUnsigned{
const size_t cell_size=sizeof(I);
std::vector<I> _integers;
public:
BigUnsigned();
BigUnsigned(I);
template<typename T>
friend std::ostream& operator<<(std::ostream& out, const BigUnsigned<T>& bu);
};
template<typename T>
std::ostream& operator<<(std::ostream& out, const BigUnsigned<T>& bu){
for (auto integer : bu._integers){
out<<integer<<std::endl;
}
return out;
}
The reason the second example works is that since it is declared inside the class it uses the template type that the class uses.
A refinement to the answer by NathanOliver.
With the other answer, all instantiations of the function template are friends of all instatiations of the class template.
operator<< <int> is a friend of BigUnsigned<int> as well as BigUnsigned<double>.
operator<< <double> is a friend of BigUnsigned<double> as well as BigUnsigned<FooBar>.
You can change the declarations a little bit so that
operator<< <int> is a friend of BigUnsigned<int> but not of BigUnsigned<double>.
operator<< <double> is a friend of BigUnsigned<double> but not BigUnsigned<FooBar>.
// Forward declaration of the class template.
template <typename I> class BigUnsigned;
// Forward declaration of the function template
template <typename I>
std::ostream& operator<<(std::ostream& out, const BigUnsigned<I>& bu);
// Change the friend-ship declaration in the class template.
template <typename I>
class BigUnsigned{
const size_t cell_size=sizeof(I);
std::vector<I> _integers;
public:
BigUnsigned();
BigUnsigned(I);
// Grant friend-ship only to a specific instantiation of the
// function template.
friend std::ostream& operator<< <I>(std::ostream& out, const BigUnsigned<I>& bu);
};
To add a third variant that improves the readability a little bit, is to define the friend function inside the class:
#include <iostream>
template <typename T>
class Foo {
int test = 42;
// Note: 'Foo' inside the class body is basically a shortcut for 'Foo<T>'
// Below line is identical to: friend std::ostream& operator<< (std::ostream &os, Foo<T> const &foo)
friend std::ostream& operator<< (std::ostream &os, Foo const &foo) {
return os << foo.test;
}
};
int main () {
Foo<int> foo;
std::cout << foo << '\n';
}
So I'm trying to overload the output operator using templates, but I keep running into two errors. They are:
Error C2988 unrecognizable template declaration/definition
and
Error C2143 syntax error: missing ',' before '<'
template <typename E> class SLinkedList; //forward declaration
template <typename E>
ostream& operator<< (ostream& out, const SLinkedList<E>& v); //forward declaration
template <typename E>
class SLinkedList {
public:
template <typename E>
friend ostream& operator<< <E>(ostream& out, const SLinkedList<E>& v);
};
template <typename E>
ostream& operator <<(ostream& out, E const SLinkedLst<E>& v) {
while (v->next != NULL) {
out << v->elem;
v->next;
}
return out;
}
<E> is not needed in
friend ostream& operator<< <E>(ostream& out, const SLinkedList<E>& v);
Just get rid of it and it should compile.
You are also missing a ; at the end of you class. In C++ a class and struct declaration must end with a ;
You have an extra E in
ostream& operator <<(ostream& out, E const SLinkedLst<E>& v) {
^ what is this doing here?
You are also missing a ; at then end of
v->next
You are also using the same template name in
template <typename E>
class SLinkedList {
public:
template <typename E>
friend ostream& operator<< <E>(ostream& out, const SLinkedList<E>& v);
};
Which E is the function referring too? You will need to change it to some other name.
Try that instead
template <typename E>
class SLinkedList {
public:
template <typename T>
friend std::ostream& operator << (std::ostream& out, const SLinkedList<T>& v);
};
template <typename E>
std::ostream& operator << (std::ostream& out, const SLinkedList<E>& v) {
while (v->next != NULL) {
out << v->elem;
v->next;
}
return out;
}
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.
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.
I declared an overloaded operator as a friend in an Xcode C++ program
template <typename T> friend class list_template;
template <typename T> friend ostream& operator<< (ostream &, list_template<T> &);
It gives me an error on the second declaration that list_template has not been declared?
If I #include the file where list_template is declared I get more problems...
You're missing a global forward declaration of list_template, if I understand what you're trying to do:
MyClass.h
// forward declarator. must match definition in list_template.h
template<typename T> class list_template;
class MyClass
{
public:
MyClass() {};
virtual ~MyClass() {};
template<typename T> friend class list_template;
template<typename T> friend ostream& operator <<(ostream&, const list_template<T>&);
};
list_template.h
template<typename T>
class list_template
{
public:
list_template() {};
virtual ~list_template() {};
// declare friend ostream operator <<
friend ostream& operator << <>(ostream& os, const list_template<T>& lt);
};
// ostream insertion operator <<
template<typename T>
ostream& operator <<(ostream& os, const list_template<T>& lt)
{
// TODO: use lt here.
return os;
}
At least I think this is near where you were going.