Why does the following code not compile (linker error, 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 cClass<int> const &)" (??6#YAAEAV?$basic_ostream#DU?$char_traits#D#std###std##AEAV01#AEBV?$cClass#H###Z))
#include <iostream>
template <class Type> class Class{
public:
friend std::ostream& operator<<(std::ostream& Stream, const Class& Op);
};
template <class Type> std::ostream& operator<<(std::ostream& Stream, const Class<Type>& Op){
return(Stream);
}
int main(){
Class<int> A;
std::cout << A;
return(0);
}
This line:
friend std::ostream& operator<<(std::ostream& Stream, const Class& Op);
Should be:
template <class T> friend std::ostream& operator<<(std::ostream& Stream, const Class<T>& Op);
Related
I'm trying to write the function definition for overloading the operators ">>" and "<<" outside of the class definition, though in the same file, as you can see. I get the following errors:
1>Source.obj : 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 MyClass<int> &)" (??5#YAAAV?$basic_istream#DU?$char_traits#D#std###std##AAV01#AAV?$MyClass#H###Z) referenced in function _main
1>Source.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 MyClass<int>)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#V?$MyClass#H###Z) referenced in function _main
1>Source.obj : 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 MyClass<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > &)" (??5#YAAAV?$basic_istream#DU?$char_traits#D#std###std##AAV01#AAV?$MyClass#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std#####Z) referenced in function _main
1>Source.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 MyClass<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#V?$MyClass#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std#####Z) referenced in function _main
I've been up and down the river with this one. The strange thing is that if I write their definitions inside the class definition, it works flawlessly.
#include <iostream>
#include <string>
using namespace std;
template <class MYTYPE>
class MyClass {
MYTYPE *myVector;
int dim;
string name;
public:
MyClass(int, string);
MyClass() {};
friend istream& operator>>(istream&, MyClass<MYTYPE>&);
friend ostream& operator<<(ostream&, MyClass<MYTYPE>);
};
template <class MYTYPE>
MyClass<MYTYPE>::MyClass(int x, string y) {
dim = x;
name = y;
myVector = new MYTYPE[dim];
}
template <class MYTYPE>
istream& operator>>(istream& X, MyClass<MYTYPE>& a){
cout<<"Reading vector: "<<a.name<<endl;
for(int indice = 0; indice < a.dim; indice++){
cout<<a.name<<'['<<indice<<"]= ";
X >> a.myVector[indice];
}
return X;
}
template <class MYTYPE>
ostream& operator<<(ostream& X, MyClass<MYTYPE> a){
X<<"Vector: "<<a.name<<endl;
for(int indice = 0; indice < a.dim; indice++)
X<<a.myVector[indice]<<' ';
X<<endl;
return X;
}
int main() {
MyClass<int> object(4, "Ints vector");
MyClass<string> object2(5, "String vector");
cin >> object;
cin >> object2;
cout << object;
cout << object2;
system("pause");
return 0;
}
In your code, declarations of friend operators within MyClass should look like these:
template<typename T> friend istream& operator>>(istream&, MyClass<T>&);
template<typename T> friend ostream& operator<<(ostream&, MyClass<T>);
That is, they shall have their own template parameters.
A valid definition for MyClass based on the one provided in the question follows:
template <class MYTYPE>
class MyClass {
MYTYPE *myVector;
int dim;
string name;
public:
MyClass(int, string);
MyClass() {}
template<typename T>
friend istream& operator>>(istream&, MyClass<T>&);
template<typename T>
friend ostream& operator<<(ostream&, MyClass<T>);
};
Turning up the warning level of the compiler helps. By using -Wall with g++, I get the following warnings before the linker error.
socc.cc:13:58: warning: friend declaration ‘std::istream& operator>>(std::istream&, MyClass<MYTYPE>& )’ declares a non-template function [-Wnon-template-friend]
friend istream& operator>>(istream&, MyClass<MYTYPE>&);
^
socc.cc:13:58: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
socc.cc:14:57: warning: friend declaration ‘std::ostream& operator<<(std::ostream&, MyClass<MYTYPE> ’ declares a non-template function [-Wnon-template-friend]
friend ostream& operator<<(ostream&, MyClass<MYTYPE>);
You need to use function templates for the operator>> and operator<< functions. You can declare them before the definition of the class with:
// Forward the class template.
template <class MYTYPE> class MyClass;
// Declare the function templates.
template <class MYTYPE>
std::istream& operator>>(std::istream&, MyClass<MYTYPE>&);
template <class MYTYPE>
std::ostream& operator<<(st::ostream&, MyClass<MYTYPE>);
Then, you'll have to use the friend declaration with the appropriate template parameter.
// This makes sure that operator>><int> is not a friend of MyClass<double>
// Only operator>><double> is a friend of MyClass<double>
friend std::istream& operator>><MYTYPE>(std::istream&, MyClass<MYTYPE>&);
friend std::ostream& operator<<<MYTYPE>(std::ostream&, MyClass<MYTYPE>);
Here's an updated version of your code that builds for me. I haven't tried to run it.
#include <iostream>
#include <string>
using namespace std;
template <class MYTYPE> class MyClass;
template <class MYTYPE>
std::istream& operator>>(std::istream&, MyClass<MYTYPE>&);
template <class MYTYPE>
std::ostream& operator<<(std::ostream&, MyClass<MYTYPE>);
template <class MYTYPE>
class MyClass {
MYTYPE *myVector;
int dim;
string name;
public:
MyClass(int, string);
MyClass() {};
friend std::istream& operator>><MYTYPE>(std::istream&, MyClass<MYTYPE>&);
friend std::ostream& operator<<<MYTYPE>(std::ostream&, MyClass<MYTYPE>);
};
template <class MYTYPE>
MyClass<MYTYPE>::MyClass(int x, string y) {
dim = x;
name = y;
myVector = new MYTYPE[dim];
}
template <class MYTYPE>
std::istream& operator>>(std::istream& X, MyClass<MYTYPE>& a){
cout<<"Reading vector: "<<a.name<<endl;
for(int indice = 0; indice < a.dim; indice++){
cout<<a.name<<'['<<indice<<"]= ";
X >> a.myVector[indice];
}
return X;
}
template <class MYTYPE>
std::ostream& operator<<(std::ostream& X, MyClass<MYTYPE> a){
X<<"Vector: "<<a.name<<endl;
for(int indice = 0; indice < a.dim; indice++)
X<<a.myVector[indice]<<' ';
X<<endl;
return X;
}
int main() {
MyClass<int> object(4, "Ints vector");
MyClass<string> object2(5, "String vector");
cin >> object;
cin >> object2;
cout << object;
cout << object2;
system("pause");
return 0;
}
It is a bit complicated. Actually there are two ways a class template can have a function friend.
For example, take this:
template <typename T>
void fun();
template <typename T>
class A
{
};
Then what do you want?
Or do you want that func<X>() be friend of A<Y> for any other Y?
Do you want that fun<X>() be friend of A<X> but not of A<Y>?
That is, should the function be able to access privater members of any specialization or only to the specialization of the same type.
My guess is that you need option 2.
The trick is that you must make friend of the function specialization so the template function must already exist: you have declare the template function first and then make it friend. Something like:
//first declare both function and class
template <typename T>
class A;
template <typename T>
void fun();
//Then define the class
template <typename T>
class A
{
//A<T> is friend to fun<T>, the specializations must match.
friend void fun<T>();
};
//And define the function
template <typename T>
void fun()
{
}
If what you want is option 1, then there is no need of the advanced declarations. Just:
template <typename T>
class A
{
//A<T> is friend to fun<X>, T and X may be different
template <class X>
friend void fun();
};
That said, your code is a bit tricky to write because of the << and the >>:
template <class MYTYPE>
class MyClass;
template <class MYTYPE>
istream& operator>>(istream& X, MyClass<MYTYPE>& a);
template <class MYTYPE>
ostream& operator<<(ostream&, MyClass<MYTYPE>);
template <class MYTYPE>
class MyClass {
// ....
friend istream& operator>> <MYTYPE>(istream&, MyClass<MYTYPE>&);
friend ostream& operator<< <MYTYPE>(ostream&, MyClass<MYTYPE>);
};
This question already has answers here:
Overloading friend operator << for template class [duplicate]
(3 answers)
Closed 7 years ago.
I'm trying to overload the << operator for a class template, but the compiler gives me a linker error. The goal is to be able to send a de-referenced base class pointer to std::cout so that the derived operator<< gets called.
Is this possible?
class IBase
{
public:
IBase() {};
virtual ~IBase() {};
};
template <typename T>
class Derived
: public IBase
{
public:
Derived(T data);
friend std::ostream& operator<<(std::ostream& os, const Derived<T>& dt);
private:
T data_;
};
template <typename T>
Derived<T>::Derived(T data)
: IBase(),
data_(data)
{
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const Derived<T>& dt)
{
os << dt.data_;
return os;
}
int _tmain(int argc, _TCHAR* argv[])
{
// Question 1
Derived<int> der(234);
std::cout << der;
// Question 2
//IBase* base = new Derived<int>(5);
// std::cout << *base
}
Here are the errors:
error LNK2001: unresolved external symbol "class
std::basic_ostream > & __cdecl
operator<<(class std::basic_ostream
&,class Derived const &)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#ABV?$Derived#H###Z)
and
fatal error LNK1120: 1 unresolved externals
You need to declarate friend operator as a template too
template<typename T1>
friend std::ostream& operator<<(std::ostream& os, const Derived<T1>& dt);
friend std::ostream& operator<<(std::ostream& os, const Derived<T>& dt);
declares a non template version friend, so you would have to implement
std::ostream& operator<<(std::ostream& os, const Derived<T>& dt);
for every T you use:
std::ostream& operator<<(std::ostream& os, const Derived<int>& dt) {
return os << dt.data_;
}
And so on.
A way to do it without duplicate code is with definition inside the class:
template <typename T>
class Derived : public IBase
{
public:
explicit Derived(T data);
friend std::ostream& operator<<(std::ostream& os, const Derived<T>& dt)
{
return os << dt.data_;
}
private:
T data_;
};
Demo
An other alternative is to make the function template.
// Forward declarations
template <typename T> class Derived;
template <typename T> std::ostream& operator<<(std::ostream& os, const Derived<T>& dt);
And then in Derived, you have 2 choices:
Declare each the template method friend:
template <typename T2>
friend std::ostream& operator<<(std::ostream& os, const Derived<T2>& dt);
So std::ostream& operator<<(std::ostream& os, const Derived<int>& dt) has access to private members of Derived<int>, but also to the ones of Derived<char>
Demo
Declare only the template which matches the argument:
friend std::ostream& operator<< <>(std::ostream& os, const Derived& dt);
and so std::ostream& operator<<(std::ostream& os, const Derived<int>& dt) doesn't have access to private members of Derived<char>.
Demo
replace
friend std::ostream& operator<<(std::ostream& os, const Derived<T>& dt);
with
template<typename D>
friend std::ostream& operator<<(std::ostream& os, const Derived<D>& dt);
Your immediate problem is that the operator needs to be templated.
However, your ultimate goal can't be attained through templates alone as dereferencing a IBase* gets you a IBase& - template instantiation occurs at compile time and the compiler has no access to the runtime type.
So your templated operator will never be used if you pass a dereferenced IBase* to operator <<.
Instead, add a virtual output function to the base and override it:
class IBase
{
public:
IBase() {};
virtual ~IBase() {};
virtual std::ostream& output(std::ostream&) const = 0;
};
template <typename T>
class Derived
: public IBase
{
public:
Derived(T data);
virtual std::ostream& output(std::ostream& os) const
{
os << data;
return os;
}
private:
T data_;
};
std::ostream& operator<<(std::ostream& os, const IBase& dt)
{
return dt.output(os);
}
You don't need to make your friend a template:
friend std::ostream& operator<<(std::ostream& os, const Derived<T>& dt);
This needs to be changed to:
friend std::ostream& operator<< <>(std::ostream& os, const Derived<T>& dt);
The operator<< function will need to be visible before the friend declaration for this form to work.
You should prefer this form to making the friend a template because you don't need all of the operator's instantiations to be friends, just one of them.
I'm trying to recreat a stack with a forward_list. However, i use friend functions to overload the + and << operator.
#pragma once
#include <forward_list>
template <class T> class Stack;
template <class T>
Stack<T> operator+(const Stack<T> &a, const Stack<T> &b){
//implementation
}
template <class T>
std::ostream &operator<<(std::ostream &output, Stack<T> &s)
{
//implementation
}
template <class T>
class Stack
{
friend Stack<T> operator+(const Stack<T> &a, const Stack<T> &b);
friend std::ostream &operator<<(std::ostream &output, Stack<T> &s);
std::forward_list<T> l;
public:
//Some public functions
};
For both of the friend functions i get an linker Error , when i try to call them in my main like:
int main(){
Stack<int> st;
st.push(4);
Stack<int> st2;
st2.push(8);
cout<<st + st2<<endl;
return 0;
}
And these are the errors:
error LNK2019: unresolved external symbol "class Stack<int> __cdecl operator+(class Stack<int> const &,class Stack<int> const &)" (??H#YA?AV?$Stack#H##ABV0#0#Z) referenced in function _main
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 Stack<int> &)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#AAV?$Stack#H###Z) referenced in function _main
Thanks in advance.
Your template friend declarations within the Stack class are not quite correct. You need to declare like this:
template<class T>
friend Stack<T> operator+(const Stack<T> &a, const Stack<T> &b);
template<class T>
friend std::ostream &operator<<(std::ostream &output, Stack<T> &s);
Since you are using MSVC, please see this Microsoft documentation for further reference.
This is my code:
mov.h
#include <iostream>
template< class T>
class Movie {
public:
Movie(T in) {
a = in;
}
friend std::ostream& operator<<(std::ostream& os, const Movie<T>& movie);
private:
T a;
};
template<class T>
std::ostream& operator<<(std::ostream& os, const Movie<T>& movie) {
return os;
}
main.cpp
#include "mov.h"
int main() {
Movie<int> movie1(1);
std::cout << movie1 << std::endl;
return 0;
}
I try to compile this code, and I get the error:
Error 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 Movie<int> const &)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#ABV?$Movie#H###Z) referenced in function _main c:\Users\Adi\documents\visual studio 2013\Projects\bdika01\bdika01\main.obj bdika01
Error 2 error LNK1120: 1 unresolved externals c:\users\adi\documents\visual studio 2013\Projects\bdika01\Debug\bdika01.exe 1 1 bdika01
If I try the code inline like this it's okay:
mov.h
#include <iostream>
template<class T>
class Movie {
public:
Movie(T in) {
a = in;
}
friend std::ostream& operator<<(std::ostream& os, const Movie<T>& movie){
return os;
}
private:
T a;
};
What can I do if I want to separate the defination and declaration?
Thanks.
template <typename T> class Movie;
template<class T>
std::ostream& operator<<(std::ostream& os, const Movie<T>& movie);
template< class T>
class Movie {
friend std::ostream& operator<< <T>(std::ostream& os, const Movie<T>& movie);
};
template<class T>
std::ostream& operator<<(std::ostream& os, const Movie<T>& movie){
return os;
}
In your original code, you befriend a non-template function that just happens to take the right instantiation of Movie<> as a parameter. So, every time a Movie<T> is instantiated, a corresponding non-template operator<< is declared (but not defined) in the enclosing namespace scope. friend declarations are strange this way.
In addition, you declare and define a function template named operator<< (which is not a friend of any instantiation of Movie). However, overload resolution prefers non-templates, other things equal.
//cstack.h
# ifndef _STACK_H__
#define _STACK_H__
#include<iostream>
#include<vector>
template< class Type ,int Size = 3>
class cStack
{
Type *m_array;
int m_Top;
int m_Size;
public:
cStack();
cStack(const Type&);
cStack(const cStack<Type,Size> &);
int GetTop()const;
bool Is_Full()const;
bool Is_Empty()const;
void InsertValue(const Type&);
void RemeoveValue();
void show();
~cStack();
friend std::ostream& operator <<(std::ostream &, const cStack<Type,Size> &);
};
// iam writing only one function defination because linking is because of this function
template< class Type,int Size >
std::ostream& operator << ( std::ostream &os, const cStack<Type,Size> &s)
{
for( int i=0; i<=s.GetTop();i++)
{
os << s.m_array[i];
}
return os;
}
//main.cpp
#include "cStack.h"
#include <string>
#include<iostream>
int main()
{
cStack<int> sobj(1);
std::cout << sobj;
}
When I compile I get the following error:
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 cStack<int,3> const &)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#ABV?$cStack#H$02###Z) referenced in function _main
35.16 Why do I get linker errors when I use template friends?
friend std::ostream& operator<< (std::ostream &, const cStack<Type, Size> &);
Mark the function as template functions
friend std::ostream& operator<< <>(std::ostream &, const cStack<Type, Size> &);
And the compiler will be happy.
And put the function definition before the class definition.
template< class Type ,int Size>
class cStack;
template< class Type ,int Size >
std::ostream& operator <<(std::ostream &os, const cStack<Type,Size> &s)
{
for( int i=0; i<=s.GetTop();i++)
{
os << s.m_array[i];
}
return os;
}
template< class Type ,int Size = 3>
class cStack
{
Type *m_array;
int m_Top;
int m_Size;
public:
cStack() {}
//...
friend std::ostream& operator<< <>(std::ostream &, const cStack<Type, Size> &);
};
I think the linker can't find your function. Place all the code in the the header file.
It's compiling, it's just not linking. (I know, that's not a big help.) You don't have a place where the function template is being instantiated. Do you have a main() somewhere that tries to use this stream insertion operator?
[snip]
The following works on windows with Visual Studio 2005
template <class Type, int Size = 3 >
class cStack
{
// ....
template<class Type>
friend std::ostream& operator<< (std::ostream & os, const cStack<Type> &s);
};
template<class Type>
std::ostream& operator << (std::ostream &os, const cStack<Type> &s)
{
for( int i=0; i < s.GetTop();i++)
{
os << s.m_array[i];
}
return os;
}