i have a template class, and when im runing the program it says
error LNK2019: unresolved external symbol "class std::basic_ostream > & __cdecl operator<<(class std::basic_ostream > &,class CSet &)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#AAV?$CSet#H###Z) referenced in function "public: void __thiscall Menu::menu(void)" (?menu#Menu##QAEXXZ)
on any kind of data structure i try to use,
if anyone can explain to me why the overloading of printing function makes this error i'll be happy to ear about it.
template <class T> class CSet{
T* Array;
int size;
public:
CSet()
{
Array = NULL;
size = 0;
}
CSet(CSet& other){
size = other.size;
Array = new T[size];
for (int i = 0; i < size; i++)
Array[i] = other.Array[i];
}
friend ostream& operator <<(ostream& out, CSet& other);
~CSet()
{
if (size > 0)
delete[] Array;
}
};
template <class T> ostream& operator <<(ostream& out, CSet<T>& other){
out << "(";
for (int i = 0; i < other.size; i++){
if (size>1)
out << other.Array[i] < ",";
else
out << other.Array[i];
}
out << ")" << endl;
return out;
}
The friend declaration does not declare a function template, but a separate function for each instantiation of the class template. Therefore, the template you define is not the same as these functions, which remain undefined.
There are two options to fix this.
Either define the friend operator inside the class, rather than just declaring it there:
friend ostream& operator <<(ostream& out, CSet& other) {
// implementation
}
Or declare the function template before the class definition:
template <class T> class CSet;
template <class T> ostream& operator <<(ostream& out, CSet<T>&);
and declare the template to be a friend:
friend ostream& operator << <T>(ostream& out, CSet&);
^^^
Related
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.
I want to overload >> and << in a templated class and I'm getting some errors.
Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol "class std::basic_istream<char,struct std::char_traits<char> > & __cdecl operator>>(class std::basic_istream<char,struct std::char_traits<char> > &,class MatricePatratica<int> &)" (??5#YAAAV?$basic_istream#DU?$char_traits#D#std###std##AAV01#AAV?$MatricePatratica#H###Z) referenced in function _main ConsoleApplication3 C:\Users\Octavian\source\repos\ConsoleApplication3\ConsoleApplication3\Source.obj 1
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 MatricePatratica<int> const &)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#ABV?$MatricePatratica#H###Z) referenced in function _main ConsoleApplication3 C:\Users\Octavian\source\repos\ConsoleApplication3\ConsoleApplication3\Source.obj 1
Error LNK1120 2 unresolved externals ConsoleApplication3 C:\Users\Octavian\source\repos\ConsoleApplication3\Debug\ConsoleApplication3.exe 1
AFAIK this happens when a function is declared but not implemented. I get those errors for overloading >> << (as you can see above)
The only thing is that I implemented those functions so I expected it to work. But I might be missing something.
Here's my templated class
#pragma once
template <typename T>
class MatricePatratica
{
private:
T** date;
int n = 0;
public:
MatricePatratica();
MatricePatratica(int);
MatricePatratica(const MatricePatratica&);
friend std::istream& operator>>(std::istream& is, MatricePatratica<T>& obj);
friend std::ostream& operator<<(std::ostream& os, const MatricePatratica<T>& obj);
};
template<typename T>
inline MatricePatratica<T>::MatricePatratica()
{
}
template<typename T>
inline MatricePatratica<T>::MatricePatratica(int n) :n(n)
{
date = new int* [n];
for (int i = 0; i < n; i++)
{
date[i] = new int[n];
}
}
template<typename T>
inline MatricePatratica<T>::MatricePatratica(const MatricePatratica& deCopiat)
{
date = new int* [deCopiat->n];
for (int i = 0; i < deCopiat->n; i++)
{
date[i] = new int[deCopiat->n];
}
for (int i = 0; i < deCopiat->n; i++)
{
for (int j = 0; j < deCopiat->n; j++)
{
date[i][j] = deCopiat[i][j];
}
}
}
template <typename T>
std::istream& operator>>(std::istream& is, MatricePatratica<T>& obj)
{
for (int i = 0; i < obj.n; i++)
{
for (int j = 0; j < obj.n; j++)
{
is >> obj.date[i][j];
}
}
return is;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const MatricePatratica<T>& obj)
{
for (int i = 0; i < obj.n; i++)
{
for (int j = 0; j < obj.n; j++)
{
os << obj[i][j] << " ";
}
os << std::endl;
}
return os;
}
and here's the main file:
#include <iostream>
#include "MatricePatratica.h"
int main()
{
MatricePatratica<int> test(5);
std::cin >> test;
std::cout << test;
}
Why am I getting this error and how should I fix it?
Live demo
Problem is that you have declared a friendship to something what is not a template!
So compiler tries to find:
std::istream& operator>>(std::istream& is, MatricePatratica<int>& obj)
Which doesn't exists, when in fact it should use:
// note extra template parameter:
std::istream& operator>><int>(std::istream& is, MatricePatratica<int>& obj)
To fix it you need declare friendship to a template of those operators:
template <typename T>
class MatricePatratica
{
....
template<typename U>
friend std::istream& operator>>(std::istream& is, MatricePatratica<U>& obj);
template<typename U>
friend std::ostream& operator<<(std::ostream& os, const MatricePatratica<U>& obj);
};
After fixing typo it works: https://wandbox.org/permlink/gHEmap8zCCTyBjRA
Here's an alternate method of getting the friend functions to work. There's a bit more code, but it has the perk of tying the friend function instantiations to those of the class.
The issue with the accepted answer is that it is too free. Say you have a MatricePatratica<int>. It has as friends all possible versions of your operator<<() and operator>>(); as in operator<< <double>() is a friend of your MatricePatratica<int> and the version for <std::string> and so on. It becomes possible to attempt to use a friend function that isn't compatible with the class type.
The version of your header below fixes that.
My reference is this link, and it contains a concrete example of how the accepted answer can bite you.
#pragma once
#include <iostream> // CHANGE: Include what you use
// CHANGE: Forward declare class and friends
template <typename T>
class MatricePatratica;
template <typename T>
std::istream& operator>>(std::istream& is, MatricePatratica<T>& obj);
template <typename T>
std::ostream& operator<<(std::ostream& os, const MatricePatratica<T>& obj);
template <typename T>
class MatricePatratica
{
private:
T** date;
int n = 0;
public:
MatricePatratica();
MatricePatratica(int);
MatricePatratica(const MatricePatratica&);
// Note movement of <T>
friend std::istream& operator>><T>(std::istream& is, MatricePatratica& obj);
friend std::ostream& operator<<<T>(std::ostream& os, const MatricePatratica& obj);
};
template<typename T>
inline MatricePatratica<T>::MatricePatratica()
{
}
template<typename T>
inline MatricePatratica<T>::MatricePatratica(int n) :n(n)
{
date = new int* [n];
for (int i = 0; i < n; i++)
{
date[i] = new int[n];
}
}
template<typename T>
inline MatricePatratica<T>::MatricePatratica(const MatricePatratica& deCopiat)
{
date = new int* [deCopiat->n];
for (int i = 0; i < deCopiat->n; i++)
{
date[i] = new int[deCopiat->n];
}
for (int i = 0; i < deCopiat->n; i++)
{
for (int j = 0; j < deCopiat->n; j++)
{
date[i][j] = deCopiat[i][j];
}
}
}
template <typename T>
std::istream& operator>>(std::istream& is, MatricePatratica<T>& obj)
{
for (int i = 0; i < obj.n; i++)
{
for (int j = 0; j < obj.n; j++)
{
is >> obj.date[i][j];
}
}
return is;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const MatricePatratica<T>& obj)
{
for (int i = 0; i < obj.n; i++)
{
for (int j = 0; j < obj.n; j++)
{
os << "TEST" /*obj[i][j]*/ << " "; // CHANGE: Due to compilation error
}
os << '\n'; // CHANGE: Best to avoid baking in obvious inefficiences
}
return os;
}
Now, per my reference, this approach is also not without its downside. There are cases where the template may not make an expected implicit conversion.
The surest way to get a friend function to behave completely as expected in a template class is to implement it inline (I mean in the class declaration). I don't believe your class will hit that edge case, and the method above is usually what I do.
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;
}
I have a template class MGraph<T>with a member function print_relation and a friend function which is ostream& operator<<(ostream& os, const MGraph<T>& other)
I follwed the instructions here and wrote this code:
template<class T>
ostream& MGraph<T>::print_relation(ostream& os) const
{
for (VertexId i = 0; i < max_size; i++)
{
for (VertexId j = 0; j < max_size; j++)
{
os << relation[i][j] << ' ';
}
os << endl;
}
return os;
}
...
template<class T>
ostream& operator<<(ostream& os, const MGraph<T>& other)
{
os << other.print_relation(os);
return os;
}
I get the following error when compiling:
1>main.obj : 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 MGraph<bool> const &)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#ABV?$MGraph#_N###Z) referenced in function "void __cdecl exec<bool>(class MGraph<bool> *)" (??$exec#_N##YAXPAV?$MGraph#_N###Z)
It appears 4 times, once for every data type (int, char, double, bool).
What did I do wrong?
In your overload of operator<<, you are doing this
os << other.print_relation(os);
And since MGraph<T>::print_relation returns std::ostream&, that is not valid. operator<< is not overloaded in such way, that it takes std::ostream& on RHS.
So, just remove the os <<.
template<class T>
ostream& operator<<(ostream& os, const MGraph<T>& other)
{
other.print_relation(os);
return os;
}
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