Template Binary Search Tree ostream overloading issue - c++

I tried to search but I couldn't find a solution and what is the meaning of the problem.
friend ostream & operator<<(ostream &os, const BST<T> &rhs);
void helperFunc(ostream & os, Node<T> *root) const;
and the definition is:
template<class T>
ostream & operator<<(ostream & os, const BST<T> &rhs)
{
rhs.helperFunc(os, rhs._root);
os << endl;
return os;
}
template<class T>
void BST<T>::helperFunc(ostream & os, Node<T> *root) const
{
if (root != NULL)
{
helperFunc(os, root->left);
os << root->value << " ";
helperFunc(os, root->right);
}
}
In main I'm using:
void main()
{
BST <int> a;
a.insert(5)
cout << a;
}
And I'm getting the following error message:
Error LNK2019 unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class BST<int> const &)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#ABV?$BST#H###Z) referenced in function _main...
Any additional info will be supplied if required.
The solution was:
template <typename U>
friend ostream & operator<<(ostream & os, const BST<U> &obj);

Overloading operator<< and operator>> in template class is a little special. Just comment this declaration and it will work:
friend ostream & operator<<(ostream &os, const BST<T> &rhs);
This is because the friend function is not a member function of the class actually. The overloaded operator<< function defined outside the class actually defines a new template function, different from that declared in the class. Although they have the same 'template class T', but indeed they are different functions. So the compile error tells you that the operator<< function of the class is not defined.
Since we have overload a new template operator<< outside the class, we can just get rid of the friend function declared in the class. The follow codes will work and I change some other functions for well explanation:
#include <iostream>
using namespace std;
template<class T>
class Node {
};
template<class T>
class BST {
public:
// friend ostream & operator<<(ostream & os, const BST<int> &rhs);
void helperFunc(ostream & os, Node<T> *root) const;
};
template<class T>
ostream & operator<<(ostream & os, const BST<T> &rhs)
{
cout << "success" << endl;
// rhs.helperFunc(os, rhs._root);
// os << endl;
return os;
}
template<class T>
void BST<T>::helperFunc(ostream & os, Node<T> *root) const
{
if (root != NULL)
{
helperFunc(os, root->left);
os << root->value << " ";
helperFunc(os, root->right);
}
}
int main()
{
BST<int> a;
// a.insert(5);
cout << a;
}

Related

overloaded << operator function : unresolved external symbol error

I've overloaded << operator to print the address in pointer member of a class. However, it throws the following error (using Visual Studio 2017). Using a normal class method does the job.
Any leads?
Error:
error LNK2019: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl IntroSmartPointers::operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class IntroSmartPointers::AutoPtr<class IntroSmartPointers::Resource> const &)" (??6IntroSmartPointers##YAAEAV?$basic_ostream#DU?$char_traits#D#std###std##AEAV12#AEBV?$AutoPtr#VResource#IntroSmartPointers###0##Z) referenced in function "void __cdecl IntroSmartPointers::main(void)" (?main#IntroSmartPointers##YAXXZ)
Code:
#include <iostream>
using namespace std;
namespace SmartPointers {
template<class T>
class AutoPtr {
private:
T* m_ptr;
public:
// constructor
AutoPtr(T* ptr = nullptr)
: m_ptr(ptr)
{}
// destructor
~AutoPtr() {
delete m_ptr;
}
friend ostream& operator<<(ostream& out, const AutoPtr<T>& ptr);
};
template<class T>
ostream& operator<<(ostream& out, const AutoPtr<T>& ptr) {
out << ptr.m_ptr;
}
class Resource {
public:
Resource() { cout << "Resource(): acquired\n"; }
~Resource() { cout << "~Resource: destroying...\n"; }
void sayHi() {
cout << "Hi\n";
}
};
}
void main() {
SmartPointers::AutoPtr<Resource> ptr{ new Resource{} };
cout << ptr << endl;
}
Your friend declares non-template operator.
In this case, you can define a friend function inside of the class body, or try the following:
template<typename T>
class AutoPtr {
// ...
template<typename U>
friend ostream& operator<<(ostream& out, const AutoPtr<U>& ptr);
};
template<class T>
ostream& operator<<(ostream& out, const AutoPtr<T>& ptr) {
out << ptr.m_ptr;
return out; // You missed this part too
}
see Template friend operators section in https://en.cppreference.com/w/cpp/language/friend
And main should return int instead of void.

Friend function still can't access private member

I have a simple C++ class, which I'm trying to add stream operators to, so it can be used with cout and cin
#include <iostream>
namespace testing_namespace {
class test {
friend std::ostream &operator<<(std::ostream &os, const test &o);
friend std::istream &operator>>(std::istream &is, test &o);
public:
void doThing();
private:
int member;
};
}
This is the implementation file:
std::ostream &operator<<(std::ostream &os, const testing_namespace::test &o) {
return os << o.member;
}
std::istream &operator>>(std::istream &is, testing_namespace::test &o) {
return is >> o.member;
}
void testing_namespace::test::doThing() {
std::cout << member << " thing" << std::endl;
}
I'm getting an error on compilation:
In function 'std::ostream& operator<<(std::ostream&, const testing_namespace::test&)':
test.cpp:8:20: error: 'int testing_namespace::test::member' is private within this context
return os << o.member;
with a similar error for operator>>. The doThing method compiles with no issues.
I'm not sure what I'm missing here - shouldn't friend functions be able to access the private members of the class test?
You need to define those functions under the namespace too. When you do that, you can omit the name of the namespace from test.
namespace testing_namespace
{
std::ostream &operator<<(std::ostream &os, const test &o) {
return os << o.member;
}
std::istream &operator>>(std::istream &is, test &o) {
return is >> o.member;
}
}

<method> was not declared in this scope

I'm trying to overload operator<< in C++ to use a recursive private method to get the content of a binary search tree as a string. I keep getting the "not declared in this scope" error despite checking the method signature for inconsistencies. I don't understand why the call to recursiveOutput() in operator<< causes this error.
operator<< definition:
friend std::ostream& operator<<(std::ostream&, const BinTree&);
recursive method definition:
void recursiveOutput(Node*, string&);
operator<< implementation:
std::ostream& operator<<(std::ostream& os, const BinTree& rhs)
{
string result;
recursiveOutput(rhs.root, result);
os << result;
return os;
}
The BinTree class has the private member "root" which is a pointer to the structure "Node".
EDIT: Example code
class BinTree
{
public:
friend std::ostream& operator<<(std::ostream&, const BinTree&);
private:
struct Node
{
string data;
Node* left;
Node* right;
};
Node* root;
void recursiveOutput(Node*, string&);
};
std::ostream& operator<<(std::ostream& os, const BinTree& rhs)
{
string result;
rhs.recursiveOutput(rhs.root, result);
os << result;
return os;
}
void BinTree::recursiveOutput(Node* currentRoot, string& result)
{
// if currentRoot is NULL return
if (currentRoot == NULL)
{
return;
}
// traverse left branch
recursiveOutput(currentRoot->left, result);
// append string from NodeData
std::ostringstream stream;
stream << *currentRoot->data;
result.append(stream.str());
result.append(" ");
// traverse right branch
recursiveOutput(currentRoot->right, result);
}
EDIT: The reason this causes an error is because operator<< is not a member of BinTree, so it cannot call a member function without a BinTree object to call it.

Operator << overloading

I'm working on my project and I want to overload operator << which should print out my object on console.
Object is called "config" and in its template class it has 4 arrays called attribute1, attribute2. attribute3 and attribute4.
So far I've tried this :
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
template<typename T> class config
{
T *attribute1, *attribute2, *attribute3, *attribute4;
string attribName1, attribName2, attribName3, attribName4;
public:
config(void)
{
attribute1 = new T[3];
attribute2 = new T[3];
attribute3 = new T[3];
attribute4 = new T[3];
}
~config(void)//destruktor
{
delete [] attribute1, attribute2, attribute3, attribute4;
}
//operatory
friend ostream& operator<<(ostream &out, const config<T> &c);
};//class ends
template <typename T> ostream& operator<<(ostream &out, const config<T> &c)
{
for(int i=0;i<3;i++)
{
out<<c.attribute1[i]<<c.attribute2[i]<<c.attribute3[i]<<c.attribute2[i];
}
return out;
}
Whenever I try to compile it, it gives some kind of weird error, but I know the problem is in the operator.
This is the error it gives :
Error 1 error LNK2001: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class config<double> const &)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#ABV?$config#N###Z) D:\Docs\Visual Studio 2010\Projects\project_v2.obj project_v2
and:
Error 2 error LNK1120: 1 unresolved externals D:\Docs\Visual Studio 2010\Projects\project_v2.exe project_v2
And line or column isnt specified.
Here's one way to solve the problem.
Declare the operator<< function first, before config is defined. In order to declare the function, you have to forward declare the class template.
template <typename T> class config;
template <typename T> std::ostream& operator<<(std::ostream &out,
const config<T> &c);
In the class, make the function a friend by using T as the template parameter.
friend ostream& operator<< <T>(ostream &out, const config &c);
// Notice this ^^^^
// This makes sure that operator<< <int> is not a friend of
// config<double>. Only operator<< <double> is a friend of
// config<double>
Here's a working program with those changes:
#include <string>
#include <iostream>
template <typename T> class config;
template <typename T> std::ostream& operator<<(std::ostream &out,
const config<T> &c);
template <typename T> class config
{
T *attribute1, *attribute2, *attribute3, *attribute4;
std::string attribName1, attribName2, attribName3, attribName4;
public:
config(void)
{
attribute1 = new T[3];
attribute2 = new T[3];
attribute3 = new T[3];
attribute4 = new T[3];
}
~config(void)//destructor
{
delete [] attribute1;
delete [] attribute2;
delete [] attribute3;
delete [] attribute4;
}
//operator
friend std::ostream& operator<< <T>(std::ostream &out,
const config &c);
};
template <typename T> std::ostream& operator<<(std::ostream &out,
const config<T> &c)
{
for(int i=0;i<3;i++)
{
out << c.attribute1[i] << " "
<< c.attribute2[i] << " "
<< c.attribute3[i] << " "
<< c.attribute2[i] << std::endl;
}
return out;
}
int main()
{
config<double> x;
std::cout << x << std::endl;
}
Output:
0 0 0 0
0 0 0 0
0 0 0 0

What's wrong with insertion operator overloading? (<< operator)

I have to overload the insertion operator in order to view my class objects in matrix format. I wrote the code but something's wrong. When I include this to my code and trying to build, compiler gives me tons of errors; when I commented that part out, the errors are gone and program works correctly. Here is the code:
template <class itemType>
ostream & operator<< (ostream & os, const Storage2D<itemType> & rhs)
{
node<itemType>* ptrRow = rhs.head;
node<itemType>* ptrColumn = rhs.head;
for(; ptrColumn->down != NULL; ptrColumn = ptrColumn->down)
{
ptrRow = ptrColumn;
for(; ptrRow->right != NULL; ptrRow = ptrRow->right)
{
os << ptrRow->info << setw(10);
}
os << ptrRow->info << setw(10) << endl;
}
return os;
}
Here is how I tried to use overloading from main function:
Storage2D<double> m(row, column);
cout << m;
It is not the member function of class Storage2D, it is written outside of the scope of class Storage2D in the implementation file.
It would be great if you help me, thanks in advance.
EDIT: Here is the rest of my code. The Storage2D.h file:
template <class itemType>
struct node
{
itemType info;
node* right;
node* down;
node()
{}
node(itemType data, node* r = NULL, node* d = NULL)
{
info = data;
right = r;
down = d;
}
};
template <class itemType>
class Storage2D
{
public:
Storage2D(const int & , const int & ); //constructor
//~Storage2D(); //destructor
//Storage2D(const Storage2D & ); //deep copy constructor
private:
node<itemType>* head;
};
ostream& operator<< (ostream & os, const Storage2D & rhs);
#include "Storage2D.cpp"
head is private so the operator needs to be a friend so it can access that data member. It also needs to be declared as a function template since Storage2D is a class template:
#include <iostream> // for std::ostream
template <class itemType>
class storage2D {
// as before
template <typename T>
friend std::ostream& operator<< (std::ostream & os, const Storage2D<T> & rhs);
};
// declaration
template <typename T>
std::ostream& operator<< (std::ostream & os, const Storage2D<T> & rhs);
Note that I have explicitly used std::ostream, since ostream is in the std namespace.