How to handle ostream operator overloading inside templated class - c++

So I have this templated class called list
//List.h
#ifndef LIST_H
#define LIST_H
#include<fstream>
template <class T>
class List
{
private:
struct ListNode
{
T value;
ListNode* next;
ListNode* prev;
ListNode(T value1, ListNode* next1 = NULL, ListNode* prev1 = NULL)
{
value = value1;
next = next1;
prev = prev1;
}
};
ListNode* head;
ListNode* tail;
public:
List() {head = NULL; tail = NULL;};
~List();
void PrintForward(std::ostream &out);
void PrintBackward(std::ostream &out);
void InsertFront(const T &item);
void InsertRear(const T &item);
bool InsertAsNth(int N, const T &item);
bool DeleteFront(T &val);
bool DeleteRear(T &val);
bool DeleteNth(int N, T &val);
int DeleteAllOccur(const T &item);
std::ostream& operator<< (std::ostream &out, List::ListNode const* p);
};
#endif
Now I have been trying to get this to compile but with no success. I know it has to do with the way I have the ostream operator overloaded but unfortunately I really do not know/could not find a better way.
also this is my compiler error
warning C4346: 'List<T>::ListNode' : dependent name is not a type prefix with 'typename' to indicate a type

std::ostream& operator<< (std::ostream &out, List::ListNode const* p);
has to become
std::ostream& operator<< (std::ostream &out, typename List::ListNode const* p);
or maybe even
std::ostream& operator<< (std::ostream &out, typename List<T>::ListNode const* p);
to be more explicit.
Because ::ListNode is a dependant type of the templated class List and the C++ compiler needs a little hint there. The warning is actually surprisingly helpful in this case, which cannot be said for many template related ones :)

The compiler error says exactly what is wrong and what you have to do: List<T>::Node is a qualified-id dependent on a template parameter, so the compiler cant be sure if Node is a type or a value. So you have to write typename before it to tell the compiler that Node is a type.
I suggest you to checkout this question: Where and why do I have to put the "template" and "typename" keywords?

There are at least two major problems with your code. The most
critical is that you are making operator<< a member, and
trying to give it three parameters, Which is completely illegal.
If the first parameter is to be an std::ostream&, there is no
way you can define it as a member; it must be a free function.
If it also needs access to private data, then you'll have to
make it a friend. But be aware:
friend std::ostream& operator<<( std::ostream&, typename List::ListNode const* );
makes a non-template function friend. A different non-template
function for each instantiation of the template. This is rarely
what is wanted. You can make a specific template instantiation
friend, but only if the template function is declared before
hand. Which is impossible in this case, because one of the
arguments of the function has a nested type. The more idiomatic
way of solving this (in my experience, anyway) is to define the
friend inline:
friend std::ostream& operator<<( std::ostream& dest, typename List::ListNode const& p )
{
// ...
}
In this case, operator<< is also a non-templated function, but
the definition is nested in the class template, so you will get
a new instance of the function automatically.

Related

ostream must take exactly one argument

I am getting a compile error in my output stream operator and I cannot seem to find out how to fix it as I never received this error before:
linkedList.cpp:258: error: ‘std::ostream& linkedList<T>::operator<<(std::ostream&, linkedList<T>)’ must take exactly one argument
make: *** [linkedList.o] Error 1
Here is the definition of my operator<<
template <class T>
ostream& linkedList<T>::operator<<(ostream &output, linkedList<T> list)
{
node *curr;
curr=list.head;
while(curr!=NULL )
{
output << curr->data;
curr = curr->next;
}
return output;
}
Here it is in my header:
//ostream operator for printing the list
template <class T>
ostream &operator<<(ostream &output, linkedList<T> list);
Any help will be appreciated!
You defined it as a member function, you have to define it as a free standing (probably friend) function, either
outside your class
template <class U>
ostream& operator<<(ostream &output, linkedList<U> list){...}
in which case you also have to declare it inside the class as
template <class U> // note the different type name
friend ostream& operator<<(ostream &output, linkedList<U> list)
or
inside the class as
// no need for template, type is passed automatically the function is not templated anymore
friend ostream& operator<<(ostream &output, linkedList list){...}
The difference between these 2 declarations is a bit subtle, but for your purpose both work equally well. And probably you want to pass linkedList by const reference, linkedList<T>& list.
EDIT
A common mistake is to just declare the friend operator inside the class as
template<typename T>
class linkedlist
{
//....
friend ostream& operator<<(ostream& output, const linkList& list); // declaration only
}
then try to define it outside the class as
template<typename T>
ostream& operator<<(ostream& output, const linkList<T>& list){...}
Guess what? The code will compile, but won't link, as the declaration inside the class declares a non-template function, one for each type T you pass to linkList<T>. Then, when you declare e.g. linkList<int> lst, and try cout << lst, the compiler will see the declaration of the friend, which for it looks like
friend ostream& operator<<(ostream& output, const linkList<int>& list);
and will try searching for its definition. However there is no definition in the rest of the header, only the template operator, so the linker isn't able to find the implementation and will spit a linker error. Live example here.
It's all in the error message. This function that you declared:
template <class T>
ostream &operator<<(ostream &output, linkedList<T> list);
is a member function of linkedList<T> that takes two arguments. All the binary operators (+, *, <<, ... all except for the call operator ()), when defined as member functions, must take exactly one argument, hence the error. What you had intended to do was to declare a non-member function, external to the class:
template <typename T>
class linkedList { .. };
template <typename T>
ostream &operator<<(ostream &output, linkedList<T> list) {
// implementation
}
You could also define it as a non-member friend inside the class definition:
template <class T>
class linkedList {
...
friend ostream &operator<<(ostream &output, linkedList list){
...
}
...
};

"X is not a member of Y" even though X is a friend of Y?

I am trying to write a binary tree. Why does the following code report error C2039, "'<<' : is not a member of 'btree<T>'" even though the << operator has been declared as a friend function in the btree class?
#include<iostream>
using namespace std;
template<class T>
class btree
{
public:
friend ostream& operator<<(ostream &,T);
};
template<class T>
ostream& btree<T>::operator<<(ostream &o,T s)
{
o<<s.i<<'\t'<<s.n;
return o;
}
In
template <typename T>
class BTree
{
// ...
friend std::ostream& operator<<( std::ostream&, T );
// ...
};
you're telling the compiler that there is a non template free function
std::ostream& operator<<( std::ostream&, Type )
for whatever type you happen to instantiate BTree over. But you never
provide such a function. The definition you provide is for a member,
but as a member function, your operator<< takes too many parameters.
Given that BTree is a generic type, it shouldn't provide the means of
displaying its contained elements; that's up to the contained element
type. What would make sense is something like:
template <typename T>
class BTree
{
struct Node
{
// ...
void display( std::ostream& dest, int indent ) const;
};
// ...
void display( std::ostream& dest ) const;
friend std::ostream& operator<<( std::ostream& dest, BTree const& tree )
{
tree.display( dest );
return dest;
}
};
template <typename T>
void BTree::display( std::ostream& dest ) const
{
if ( myRoot == NULL ) {
dest << "empty";
} else {
myRoot->display( dest, 0 );
}
}
template <typename T>
void BTree::Node::display( std::ostream& dest, int indent ) const
{
dest << std::string( indent, ' ' ) << data;
if ( myLeft != NULL ) {
myLeft->display( dest, indent + 2 );
}
if ( myRight != NULL ) {
myRight->display( dest, indent + 2 );
}
}
By declaring the operator friend, you tell the compiler to look for a function
ostream& operator<<(ostream &,T);
where T is the exact same type the btree class template is instantiated with. (e.g. for btree<Node>, the actual signature would be ostream& operator<<(ostream &, Node); -- assuming you hace members i and n of type Node)
This function will have access to private and protected members (variables and functions) of the class btree<T> for all instances of T, but it is not actually a member of the class (as it would be without the friend keyword).
The operator definition you provide is for an operator that is a member of the template class btree, as if you have declared
template<class T>
class btree
{
public:
ostream& operator<<(ostream &,T);
};
This is due to the btree<T>:: prefix you included (that specifies which class the function/operator belongs to).
Since there is no corresponding operator declaration in the class (see the above description of the friend declaration), the compiler complains.
To fix it, you either
keep the friend declaration, remove the btree<T>:: prefix and template<class T> from the operator defintion and change the second parameter type to btree<Type>&, where Type is one of the types you expect the btree template to be instantiated with (e.g. Node) -- then supply similar defintions for other such types as well.
or remove the friend keyword from the declaration in the class and remove the T parameter from both the declaration and the definition as now the operator is supposed to work on the whole btree (which is implicitly supplied via *this).
Alternatively, you can experiment with declaring the friend operator as a template, but that requires some more modifications: (read more about forward declaration)
template<class T> btree; // forward declaration of class btree
// forward declare operator (or move definition here)
template<class T>
ostream& operator<<(ostream &o, btree<T>& s);
// declare operator as template friend
template<class T>
class btree
{
public:
friend ostream& operator<< <> (ostream &, bree<T>&);
// note <> after operator name to denote template with no new template parameters
};
Note that above I assumed that you want to output the whole tree (that is invoke the operator<< on a btree object). It is not clear from the code you have whether this is your intention (class btree does not have members i and n). If not, and the type you want to invoke the << operator on is the actual template parameter of btree, then you don't need to change the second parameter of the templated operator from T, but there is also no need to declare it as friend of class btree as the operator is independent of btree. You do need to declare it as friend of the class whose members i and n you are accessing in the definiton of the operator (e.g Node above), if i and/or n is private in that class. The notion about losing btree<T>:: (or Node::) still applies as the operator does not belong to any class.
Couple more things, assuming you go with the friend declaration:
The type of the second parameter to the operator should be btree<T>& (emphasis on &) as it is more efficient to pass a reference to the btree object than to copy the entire btree (or a shallow copy if you use pointers and go with the default copy-contructor)
the second parameter should also be marked const, as (presumably) you do not want to change the btree object during output. Be aware that in this case you will need to mark certain non-changing methods in btree<T> as const as well to allow it to compile. (See the FAQ on const correctness)
EDIT'd a few times to make it clear and ensure correctness
A friend function is granted the same access to members of a class that members get, but it is not a member.
That's the whole point of the friend keyword, to give this access to non-members.
Since your operator<< doesn't use btree<T>, there's no reason to make it a friend of btree<T>.
So I think you meant
friend ostream& operator<<(ostream &, const mydata&);
inside class mydata.
Replace:
template<class T>
ostream& btree<T>::operator<<(ostream &o,T s)
{
o<<s.i<<'\t'<<s.n;
return o;
}
with:
ostream& operator<<(ostream &o, const mydata &s)
{
o<<s.i<<'\t'<<s.n;
return o;
}
As Ben Voight mentions, the error is telling you that this function is not a member of btree. Also, you seem to be defining that function for mydata exclusively, since it's expecting s and i members.
EDIT
Because it's a friend function, C++ is a bit weird. See, friend functions aren't actually defined in the class, they're defined in a different namespace. You have to provide an output function used by operator<< inside the class definition if you want it to use a templated member function.
The reason I suggest the following method (stream_out) is to demonstrate an easy way to do it in a way that makes it a member and doesn't mislead readers of your code, because it isn't a clever hack.
94% of the time you can use a clever hack such as has been suggested in the comments, but it does not answer the fundamental question: your 'friend' function is not a member of your class unless its body is given in the declaration, period, nothing else to say on the matter.
(What is the other 6% of the time, you ask, that this is not OK? copy constructor nonsense, CLI, and other unspeakable bumps in the night.)
If you absolutely must include it outside, as a member function, you would do something like...
template<class T>
class btree
{
private:
int i;
int n;
void stream_out(std::ostream& o);
public:
friend std::ostream& operator<<(std::ostream& o, btree<T> & me) {
me.stream_out(o);
return o;
}
};
template <class T>
void btree<T>::stream_out(std::ostream& o)
{
o << i << '\t' << n;
}
EDITED to clear up the summary a bit.

How to resolve the following errors?

I am getting the following errors- errors whenever i try to compile the following program- http://codepad.org/Bf9l8j9H in VS 2010.
Any idea how to resolve the errors??
That is a linker error, and it indicates that you have declared but not defined (or the definition is not linked) the following overload:
std::ostream& operator<<( std::ostream&, node<weight>& );
The common checks to do from here would be checking whether you have a definition, whether the definition signature matches the declaration (have you declared that, but defined the operator taking a const reference?), whether the definition is being compiled and linked...
I just got a few time and actually read the code, which I will basically condense into this:
template <typename T>
struct node {
friend std::ostream& operator<<( std::ostream&, node<T>& ); // [1] !!!!
};
template <typename T>
std::ostream& operator<<( std::ostream& o, node<T>& n ) {} // [2]
This is a common mistake and one of the reasons why it is simpler just to inline the definition of friend functions inside the templates that befriend them. Basically, in [1] your template is declaring (and befriending) a non-templated function that takes an ostream& and a node<T>& object.
The subtlety here is that when the template is instantiated for some particular type, and the friend declaration is processed, T is fixed and that line befriends a free non-templated function. For example, if you instantiate node with int, as in node<int> n, the compiler will inject int and replace T with it, then the friend declaration will be: friend ostream& operator<<( ostream&, node<int>& ), and that in turn declares a free function in the enclosing namespace. Making that declaration explicit (and assuming that you only instantiate the template with int, your code is read by the compiler as:
template <typename T> struct node {
friend ostream& operator<<( ostream&, node& ); // [1] note <T> not required here
};
// instantiating with int:
ostream& operator<<( ostream&, node<int>& ); // [3] declaration, not definition
template <typename T>
ostream& operator<<( ostream&, node<T>& ) {} // [2] your definition
At this point, whenever you type std::cout << a_int_node; the compiler will consider all overloads, it will find a non-templated free function [3] that is a perfect match, and a templated version [2], but the non-templated version will take precedence. The compiler will not instantiate the templated operator<< and will expect that you manually define the function in one translation unit.
Solutions
Simplest best solution is having the compiler generate the free function for you. You can just provide the operator definition inside the templated class and everything will be nice and simple:
template <typename T>
struct node {
friend std::ostream& operator<<( std::ostream& o, node& n ) // [1]
{ /* code goes here */ return o; }
};
Even if the code is inside the template, because of the friend being there, you are actually declaring and defining the function at namespace level. If you instantiate the template with int, the compiler will generate: std::ostream& operator<<( std::ostream&, node<int>& ) for you in the enclosing namespace.
This solution is the best of all worlds: you only grant access to a single piece of code, and the compiler takes care of most of the gory details.
On the other end, you can befriend a whole template function. The syntax for that would be:
template <typename T>
struct node {
template <typename U>
friend std::ostream& operator<<( std::ostream&, node<U>& ); // [4]
};
template <typename T>
std::ostream& operator<<( std::ostream& o, node<T>& n ) // can access private parts
{ /* code goes here */ return o; }
In this case, you are opening all instantiations of node to all instantiations of the templated function, which semantically is opening the class to other users.
The third option is befriending a single template instantiation, this will have the same effect as the first option with the only difference that instead of a non-templated free function you are using a templated one. On the other hand, the syntax is quite more cumbersome as it requires declaring the function template before befriending, and that in turn requires declaring the class template:
template <typename T> struct node; // forward declare the class template
template <typename T>
std::ostream& operator<<( std::ostream&, node<T>& ); // declare function template
template <typename T>
struct node { // define class template
friend std::ostream& operator<< <>( std::ostream&, node<T>& ); // befriend instantiation
};
template <typename T>
std::ostream& operator<<( std::ostream& o, node<T>& n ) // define function template
{ ... }
As you see, the simplest best solution is just defining the function template inside the class definition.
conio.h is an old header from the MS-DOS compilers; UPDATE: it is still available in VS 2010, though.
best is a stream you declared after you used it.

template class and insertion extraction overloaded

How can I make the insertion (<<) and/or extraction (>>) operator overloaded in a template class WITHOUT making it inline. I would like to have the << or >> operator as a friend class.
I know how to make it inline
example of inline in a matrix class
friend ostream& operator<<(ostream& ostr, const Matrix<T>& inputMatrix)
{
...
// create the ostr
return ostr;
}
but I'd like to have the code outside of the templateclass definition.
g++ told me to add <> after the function name so I did but when I tried to instansiate a matrix of type SOMETYPE it gave me an error that it didn't know how to extract or insert for that type.
If you really want to define the operator externally and befriend only the operator instantiation that coincides in type with this template instantiation, the correct syntax is:
template <typename T> class test; // forward declare template class
template <typename T> // forward declare the templated operator
std::ostream& operator<<( std::ostream&, test<T> const & );
template <typename T>
class test { // define the template
friend std::ostream& operator<< <T>( std::ostream&, test<T> const & ); // befriend
};
template <typename T> // define the operator
std::ostream& operator<<( std::ostream& o, test<T> const & ) {
return o;
}
In most cases it is not worth the hassle to pull the definition out of the class, considering that you still need to provide it in a header and the extra work required.
Also note that there are slight differences for the compiler regarding lookup. In the case where the function is inlined inside the class definition, the compiler will not find that function unless one of the arguments is actually of the type of the template, so it effectively reduces the visibility and the amount of work that the compiler has to do (if the templated operator<< is defined outside of the class, the compiler will find it as a candidate for overload resolution in all places where it finds a << b, only to discard it in all cases where the second argument is not a test<T> (and it will show the templated operator as a candidate in all error messages where it cannot match operator<<, which is a long enough list already).
Try something like:
template <typename T> class Matrix;
template <typename T> std::ostream& operator<<(std::ostream& ostr, const Matrix<T>& m);
template <Typename T>
class Matrix
{
public:
friend ostream& operator<< <T> (ostream& ostr, const Matrix<K>& inputMatrix);
};
// This must be in the same translation unit as the class definition!
template<typename T>
ostream& operator<<(ostream& ostr, const Matrix<T>& inputMatrix)
{
// ...
return ostr;
}
Translation unit reference
re-re-edited to addressed the comments made by aschepler and dribeas.
Place the code in the header, outside the class definition. Or, place it in a .tcc file and include it at the bottom of the header.

template class c++

i try to design a template for my university project. i wrote the follwing code:
#ifndef _LinkedList_H_
#define _LinkedList_H_
#include "Link.h"
#include <ostream>
template <class L>//error one
class LinkedList
{
private:
Link<L> *pm_head;
Link<L> * pm_tail;
int m_numOfElements;
Link<L>* FindLink(L * dataToFind);
public:
LinkedList();
~LinkedList();
int GetNumOfElements(){return m_numOfElements;}
bool Add( L * data);
L *FindData(L * data);
template <class L> friend ostream & operator<<(ostream& os,const LinkedList<L> listToprint);//error two
L* GetDataOnTop();
bool RemoveFromHead();
L* Remove(L * toRemove);
this templete uses the link class templete
#ifndef _Link_H_
#define _Link_H_
template <class T>//error 3
class Link
{
private:
T* m_data;
Link* m_next;
Link* m_prev;
public:
Link(T* data);
~Link(void);
bool Link::operator ==(const Link& other)const;
/*getters*/
Link* GetNext()const {return m_next;}
Link* GetPrev()const {return m_prev;}
T* GetData()const {return m_data;}
//setters
void SetNext(Link* next) {m_next = next;}
void SetPrev(Link* prev) {m_prev = prev;}
void SetData(T* data) {m_data = data;}
};
error one: shadows template parm `class L'
error two:declaration of `class L'
error three: shadows template parm `class T'
i dont understand what is the problem. i can really use your help
thank you :)
These error messages really belong together:
a.cc:41: error: declaration of ‘class L’
a.cc:26: error: shadows template parm ‘class L’
This means that in line 41, you introduce a template parameter L; in my copy, this refers to
template <class L> friend ostream & operator<<(ostream& os,
const LinkedList<L> listToprint);//error two
And that declaration shadows the template parameter in line 26:
template <class L>//error one
class LinkedList
You need to rename the template parameter in the friend declaration.
Edit: The relevant language specification is 14.6.1/7
A template-parameter shall not be
redeclared within its scope (including
nested scopes). A template-parameter
shall not have the same name as the
template name.
When you refer to L in const LinkedList<L> listToprint, it's not clear whether you mean the L of the friend or the L of the class. So write
template <class L1> friend ostream & operator<<(ostream& os,
const LinkedList<L1> listToprint);
Just remove the
template <class L>
from the friend member function declaration.
You also need to replace uses of ostream with std::ostream unless you have a using namespace std somewhere in your code.
Otherwise, the code looks fine.