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){
...
}
...
};
Related
This question already has answers here:
overloading friend operator<< for template class
(5 answers)
Closed 2 years ago.
I want to overload the << operator in my template class, and define it outside the template class.
using namespace std;
template <class T> class Child {
public:
friend ostream &operator << (ostream &Output, const Child &Object);
};
// What can I change to make my code work?
ostream &operator << (ostream &Output, const Child <T> &Object) {
}
As you can see, I don't know what the correct syntax is so that my code can run without errors. My C++ book does not go this in-depth. This has been really frustrating me so I would appreciate any help. Thank you :)
It needs to be a function template if you're going to have it accept a templated type (const Child<T> &Object). So try:
template <class T>
std::ostream &operator << (std::ostream &Output, const Child<T> &Object)
{ ... }
That should get you farther along.
The cleanest way is:
template <class T>
class Child {
void print(std::ostream& os)const;
public:
friend std::ostream &operator << (std::ostream &Output, const Child &Object){
Object.print(Output);
return Output;
}
};
// implement Child<T>::print here
a minimal amout of "glue" inline in the friend operator, forwarding to a conventional method with the meat in it.
This makes the syntax obvious to readers, and I find non-template friends of templates to be more sane than the other alternatives (like template friends to template types).
Firstly, since class templates typically need to be defined in a header (in order to use them effectively from multiple source files) remove the using namespace std and refer to ostream as std::ostream. A quick search will find numerous explanations of why using directives (like using namespace std) are best avoided in header files.
This means changing the class definition to
template <class T> class Child
{
public:
friend std::ostream &operator << (std::ostream &Output, const Child &Object);
};
The definition of the function (outside the class definition) may then be changed to
template<class T> std::ostream &operator << (std::ostream &Output, const Child <T> &Object)
{
// presumably operations that stream members of Object to Output in some way
return Output;
}
Please consider the following C++ program:
#include <iostream>
using namespace std;
template <class T> class Array
{
T *pType;
int itsSize;
public:
// template <class T>
friend ostream &operator<< (ostream &, Array<T> & );
};
template <class T>
ostream &operator<< (ostream &output, Array<T> &theArray)
{
return (output);
}
ostream &operator<< (ostream &, Array<int> &);
int main ()
{
Array<int> theArray;
cout << theArray << endl;
return 0;
}
The above code compiles but the linker gives the following error:
undefined symbol `operator<<(std::ostream&, Array&)'
I believe I need to tell the compiler to instantiate a function for the operator << but I do not know how to do that.
Bob
No, you don't need to tell the compiler to instantiate a template, it does that all by itself, if and when needed.
Your line
ostream &operator<< (ostream &, Array<int> &);
actually tells the compiler that you have some other operator for Array<int> so that it shouldn't use the template for that type.
So the linker goes looking for this other operator, but of course doesn't find any.
If you just remove that extra declaration, it should work much better.
The declaration
ostream &operator<< (ostream &, Array<int> &);
is not telling the compiler to instantiate the template. It is declaring a separate and distinct non-templated function i.e. overloading.
Within main(), the usage of operator<<() resolves to the declared function. The compiler does not need to specialize the template to find a match. However, since there is no definition (i.e. implementation) of that function, the linking fails.
Remove that declaration and you should find that your code compiles and links.
Incidentally, output streaming operators generally don't change the object being output. It is therefore advisable to change the templated ostream &operator<< (ostream &, Array<T> & ) to be ostream &operator<< (ostream &, const Array<T> & )
Also, since templates (typically) need to be defined in header files, and header files are included in multiple source files, it is better to avoid using namespace std, and replace ostream with std::ostream.
There are issues with your code, #BoPersson and #Perter pointed out some.
But even if you change what they suggested (Here is a live demo on ideone) and I ran it on my VS 2015 too. The compilers are still mad.
Ideone says:
prog.cpp:10:55: warning: friend declaration 'std::ostream& operator&)' declares a non-template function [-Wnon-template-friend]
friend ostream &operator & );
^
prog.cpp:10:55: note: (if this is not what you intended, make sure the function template has already been declared and add after the function name here)
/home/FHMhT9/ccNwcxP0.o: In function `main':
prog.cpp:(.text.startup+0x1b): undefined reference to `operator&)'
collect2: error: ld returned 1 exit status
And VS gives the pretty much same errors too.
Ideone is telling me, that the friend declaration in the class declares a non-template function.
So, change the declaration in the class to:
friend ostream &operator<< <T> (ostream &, Array<T> & );
// ^^^^^
// I added this <T> to tell the compiler that it is a template function.
But you need to define the function before this, so cut the implementation of operator<< and then paste it before the class. But you'd need a forward declaration of the class for that to work. So finally your code becomes pretty much like this:
And I changed the Array<T> & to const Array<T> & too.
#include <iostream>
template <typename T>
class Array;
template <class T>
std::ostream &operator<< (std::ostream &output, const Array<T> &theArray)
{
output << "abc";
return (output);
}
template <class T> class Array
{
T *pType;
int itsSize;
public:
// template <class T>
friend std::ostream &operator<< <T> (std::ostream &, const Array<T> &);
};
int main()
{
Array<int> theArray;
std::cout << theArray << std::endl;
return 0;
}
and this version now works.
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 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.
do you know, how to write signature of a function or method for operator<< for template class in C++? I want something like:
template <class A> class MyClass{
public:
friend ostream & operator<<(ostream & os, MyClass<A> mc);
}
ostream & operator<<(ostream & os, MyClass<A> mc){
// some code
return os;
}
But this just won't compile. Do anyone know, how to write it correctly?
All the below said, if you don't need an operator to be a friend, then don't make it a friend. For output operators in particular, in my opinion you should not make them friends. That is because if your class can be output to a stream, it should have equivalent get functions that provide the same data programmatically. And in that event, you can write a operator<< as a non-friend in terms of those get functions.
In case you have some good reason for making them friends, you can do a friend definition
template <class A> class MyClass {
public:
friend ostream & operator<<(ostream & os, MyClass<A> const& mc) {
// ...
}
};
That way you don't need the template<...> clause that gets you the type A. It's alreay known if you define the operator inside the template. Note that even though you defined it inside the template, it's not a member function. It's still a non-member, but has access to the names declared in the class (like the template parameter). For each instance of MyClass you create, a different non-template operator function is created out of that friend function that prints things.
If you want to define the template outside, you have to predeclare it to be able to declare a given specialization of it as a friend.
// predeclare it so you can make it a friend.
template <class A> class MyClass;
template <class A> ostream &operator<<(ostream &os, MyClass<A> const&);
template <class A> class MyClass{
public:
/* the "<A>" is needed - it says that a given instantiation of
that template is a friend, and not a non-template function. */
friend ostream & operator<< <A>(ostream & os, MyClass<A> const& mc);
};
template <class A>
ostream & operator<<(ostream & os, MyClass<A> const& mc){
// some code
return os;
}
That makes operator<< <Foo> a friend of MyClass<Foo>. If you were to omit the <A> or an also possible empty <>, the compiler would understand that as saying you made a non-template operator having concrete instead of templated parameters as friend.
The more easy but less "correct" solution is to make MyClass <Foo> have as friend all the operator << instantiations. So theoretically operator << <Bar> could access private members of MyClass <Foo>. It's not what is wanted, but it works too, gaining more access than needed. It gets rid of the need for forward declaring:
template <class A> class MyClass{
public:
/* make all instantiations friends. */
template<typename T>
friend ostream & operator<<(ostream & os, MyClass<T> const& mc);
};
template <class T>
ostream & operator<<(ostream & os, MyClass<T> const& mc){
// some code
return os;
}