I can't tell which part of this code is wrong. Error message is given below.
I want to overload the << operator so that I can write code like cout << tree. I looked up for information about templates, friend functions, operator overloading. But I still don't get why the error.
template <typename Value>
class Tree {
protected:
Node<Value>* root = NULL;
int size = 0;
std::ostream& _ostreamOperatorHelp(Node<Value>* node, int level,
std::ostream& os) {
...
}
public:
friend std::ostream& operator<< <Value>(std::ostream& os,
Tree<Value> const& tree);
};
template <typename Value>
std::ostream& operator<<(std::ostream& os, Tree<Value> const& tree) {
tree._ostreamOperatorHelp(tree.GetRoot(), 0, os);
return os;
}
Error message:
Tree.hpp:129:34: error: declaration of 'operator<<' as non-function
friend std::ostream& operator<< <Value>(std::ostream& ,
^~
Before you can befriend specific template specialization, you have to declare the general template function first like this:
template <typename Value>
class Tree;
template <typename Value>
std::ostream& operator<<(std::ostream& os, Tree<Value> const& tree);
template <typename Value>
class Tree {
protected:
Node<Value>* root = NULL;
int size = 0;
std::ostream& _ostreamOperatorHelp(Node<Value>* node, int level,
std::ostream& os) {
...
}
public:
friend std::ostream& operator<< <Value>(std::ostream& os,
Tree<Value> const& tree);
};
template <typename Value>
std::ostream& operator<<(std::ostream& os, Tree<Value> const& tree) {
tree._ostreamOperatorHelp(tree.GetRoot(), 0, os);
return os;
}
Related
I was reading litb's answer to a question here, where he details how to create a specialized friend function of a class template.
I tried to create an exemplar which did just what he suggests (code at the end):
// use '<>' to specialize the function template with the class template's type
friend std::ostream& operator<< <>(std::ostream& os, const foo<T>& f)
It results in a compiler error:
error: defining explicit specialization ‘operator<< <>’ in friend declaration
Explicitly declaring the template parameter in the specialization doesn't work either:
friend std::ostream& operator<< <T>(std::ostream& os, const foo<T>& f) // same error
On the other hand, changing from using a specialization to use a friend function template instead does work:
template<typename U>
friend std::ostream& operator<<(std::ostream& os, const foo<U>& f) // this works
So my questions are:
what is causing the first error?
how can I explicitly specialize the ostream operator for the surrounding class template specialization?
Exemplar code below:
#include <iostream>
// fwd declarations
template<typename T> struct foo;
template<typename T> std::ostream& operator<<(std::ostream&, const foo<T>&);
template<typename T>
struct foo
{
foo(T val)
: _val(val)
{}
friend std::ostream& operator<< <>(std::ostream& os, const foo<T>& f) // error line
//template<typename U>
//friend std::ostream& operator<<(std::ostream& os, const foo<U>& f) // this works
{
return os << "val=" << f._val;
}
T _val;
};
int main()
{
foo<std::string> f("hello world");
std::cout << f << std::endl;
exit(0);
}
In litb's example, he's just declaring the specialization as a friend in the class. He's not defining the specialization, which is what your code's doing. You're not allowed to define a specialization in a class declaration (or any non-namespace scope).
What you need is something like:
template <class T>
class foo;
template<class T>
std::ostream& operator<<(std::ostream& os, const foo<T>& f)
{
return os << "val=" << f._val;
}
template<typename T>
struct foo
{
// ...
private:
friend std::ostream& operator<< <>(std::ostream& os, const foo<T>& f);
T _val;
};
You have 2 choices:
Remove fwd declarations and define everything in class.
Example
template <typename U>
friend std::ostream& operator<<(std::ostream& os, const foo<U>& f) // this works
{
return os << "val=" << f._val;
}
Define friend function outside of the class.
Example
template<typename T> struct foo;
template<typename T> std::ostream& operator<<(std::ostream&, const foo<T>&);
template<typename T>
struct foo
{
foo(T val)
: _val(val)
{}
friend std::ostream& operator<< <>(std::ostream& os, const foo<T>& f);
T _val;
};
template <typename T>
std::ostream& operator<<(std::ostream& os, const foo<T>& f)
{
return os << "val=" << f._val;
}
I'd like to implement operator<< for my templated class so that it can print all the elements it contains to the given std::ostream&. The issue is that I can't seem to get it to recognize the function that I've defined.
The error I get is
error: no match for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream<char>}' and 'Outer<int>::Inner')
os << inner << ", ";
~~~^~~~~~~~
Ideally I'd like not to have the function defined inline, but I can't even get it to work inline. In the code below you can see that I've commented out my attempt at defining it outside the class declaration. It produces the same error as above.
This question recommends making the operator a friend of the class. I've done that every way I can think of and it still doesn't work.
The code:
#include <iostream>
template<class T>
class Outer {
class Inner {
T item;
template<class T_>
friend std::ostream& operator<<(std::ostream& os, const typename Outer<T_>::Inner& inner) {
os << inner.item;
return os;
}
template<class T_>
friend std::ostream& operator<<(std::ostream& os, const Outer<T_> outer);
};
std::vector<Inner> inner_items;
template<class T_>
friend std::ostream& operator<<(std::ostream& os, const Outer<T_> outer);
template<class T_>
friend std::ostream& operator<<(std::ostream& os, const typename Outer<T_>::Inner& bar);
};
/*template<class T>
std::ostream& operator<<(std::ostream& os, const typename Outer<T>::Inner& bar) {
os << inner.item;
return os;
}*/
template<class T>
std::ostream& operator<<(std::ostream& os, const Outer<T> outer) {
for (typename Outer<T>::Inner inner : outer.inner_items) {
os << inner << ", ";
}
return os;
}
int main()
{
Outer<int> outer;
std::cout << outer;
}
Do not make the output operator for the nested types templates:
#include <iostream>
#include <vector>
template<class T>
class Outer {
class Inner {
T item;
friend std::ostream& operator<<(std::ostream& os, typename Outer<T>::Inner const& inner) {
os << inner.item;
return os;
}
friend std::ostream& operator<<(std::ostream& os, const Outer<T> outer);
};
template <typename T_>
friend std::ostream& operator<< (std::ostream&, Outer<T_> const&);
std::vector<Inner> inner_items;
};
template<class T>
std::ostream& operator<<(std::ostream& os, Outer<T> const& outer) {
for (typename Outer<T>::Inner const& inner : outer.inner_items) {
os << inner << ", ";
}
return os;
}
int main()
{
Outer<int> outer;
std::cout << outer;
}
There are a few const& sprinkled and a necessary friend declaration added, too.
You don't need (neither want) to templetize in Inner, just use the type:
class Outer {
class Inner {
T item;
friend std::ostream& operator<<(std::ostream& os, const Inner& inner) {
os << inner.item;
return os;
}
// ...
What you wrote above fails because you define a free function in Outer<T>::Inner which is operator<<(..). The second parameter is Outer<T_>::Inner and the compiler cannot go from Inner to the type in which it was defined.
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 was reading litb's answer to a question here, where he details how to create a specialized friend function of a class template.
I tried to create an exemplar which did just what he suggests (code at the end):
// use '<>' to specialize the function template with the class template's type
friend std::ostream& operator<< <>(std::ostream& os, const foo<T>& f)
It results in a compiler error:
error: defining explicit specialization ‘operator<< <>’ in friend declaration
Explicitly declaring the template parameter in the specialization doesn't work either:
friend std::ostream& operator<< <T>(std::ostream& os, const foo<T>& f) // same error
On the other hand, changing from using a specialization to use a friend function template instead does work:
template<typename U>
friend std::ostream& operator<<(std::ostream& os, const foo<U>& f) // this works
So my questions are:
what is causing the first error?
how can I explicitly specialize the ostream operator for the surrounding class template specialization?
Exemplar code below:
#include <iostream>
// fwd declarations
template<typename T> struct foo;
template<typename T> std::ostream& operator<<(std::ostream&, const foo<T>&);
template<typename T>
struct foo
{
foo(T val)
: _val(val)
{}
friend std::ostream& operator<< <>(std::ostream& os, const foo<T>& f) // error line
//template<typename U>
//friend std::ostream& operator<<(std::ostream& os, const foo<U>& f) // this works
{
return os << "val=" << f._val;
}
T _val;
};
int main()
{
foo<std::string> f("hello world");
std::cout << f << std::endl;
exit(0);
}
In litb's example, he's just declaring the specialization as a friend in the class. He's not defining the specialization, which is what your code's doing. You're not allowed to define a specialization in a class declaration (or any non-namespace scope).
What you need is something like:
template <class T>
class foo;
template<class T>
std::ostream& operator<<(std::ostream& os, const foo<T>& f)
{
return os << "val=" << f._val;
}
template<typename T>
struct foo
{
// ...
private:
friend std::ostream& operator<< <>(std::ostream& os, const foo<T>& f);
T _val;
};
You have 2 choices:
Remove fwd declarations and define everything in class.
Example
template <typename U>
friend std::ostream& operator<<(std::ostream& os, const foo<U>& f) // this works
{
return os << "val=" << f._val;
}
Define friend function outside of the class.
Example
template<typename T> struct foo;
template<typename T> std::ostream& operator<<(std::ostream&, const foo<T>&);
template<typename T>
struct foo
{
foo(T val)
: _val(val)
{}
friend std::ostream& operator<< <>(std::ostream& os, const foo<T>& f);
T _val;
};
template <typename T>
std::ostream& operator<<(std::ostream& os, const foo<T>& f)
{
return os << "val=" << f._val;
}