This question already has answers here:
C++ template/ostream operator question
(2 answers)
What is the right way to write friend function declarations in template class?
(1 answer)
overloading friend operator<< for template class
(5 answers)
Closed 1 year ago.
I am using Microsoft Visual Studio for source code editor, and when I try to compile the below code I got an linker 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 X<int> &)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#AAV?$X#H###Z) referenced in function _main Zadatak7.19.04.2021 C:\Users\AT95\Desktop\Zadatak7.19.04.2021\Zadatak7.19.04.2021\main.obj 1
What must I do to make this program work correctly?
I want you to look at the definition of the overloading operator<< because
that method is causing errors.
#include <iostream>
template <class T>
class X
{
private:
int index, capacity;
T* collection{};
public:
X(const int nmb, const T* array)
{
index = 0;
capacity = nmb;
collection = new(T[nmb]);
for (int i = 0; i < nmb; i++)
collection[index++] = array[i];
}
X(const X& other)
{
index = other.index;
capacity = other.capacity;
collection = new(T[other.capacity]);
if(other.index < other.capacity)
for (int i = 0; i < other.index; i++)
collection[i] = other.collection[i];
}
~X() { delete[] collection; }
friend std::ostream& operator<<(std::ostream&, X<T>&);
};
template <class T>
std::ostream& operator<<(std::ostream& out, X<T>& other)
{
for (int i = 0; i < other.index; i++)
out << i + 1 << ". " << other.collection[i];
return out;
}
int main()
{
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, n = sizeof(array)/sizeof(int);
X<int> x(n, array), b(x);
std::cout << x;
return 0;
}
Your friend dclaration is wrong.
friend std::ostream& operator<<(std::ostream&, X<T>&);
This is a friend declaration of a non templated operator<<.
It should look like this:
template<typename Z>
friend std::ostream& operator<<(std::ostream&, X<Z>&);
But there is a better way to declare it. Move the function body into the class then you don't need to declare the template part.
template <class T>
class X
{
// STUFF AS BEFORE
// Friend class definition.
friend std::ostream& operator<<(std::ostream& out, X& other)
{
for (int i = 0; i < other.index; i++)
out << i + 1 << ". " << other.collection[i];
return out;
}
}
Secondary note. In output operators the object being output is usually declared const (as outputting it should not modify it).
friend std::ostream& operator<<(std::ostream& out, X const& other)
^^^^^
You need to write the template keyword at the beginning of the friend function, like this:
#include <iostream>
template <class T>
class X
{
private:
int index, capacity;
T* collection{};
public:
X(const int nmb, const T* array)
{
index = 0;
capacity = nmb;
collection = new(T[nmb]);
for (int i = 0; i < nmb; i++)
collection[index++] = array[i];
}
X(const X& other)
{
index = other.index;
capacity = other.capacity;
collection = new(T[other.capacity]);
if(other.index < other.capacity)
for (int i = 0; i < other.index; i++)
collection[i] = other.collection[i];
}
~X() { delete[] collection; }
template<class U> friend std::ostream& operator<<(std::ostream&, X<U>&);
};
template <class T>
std::ostream& operator<<(std::ostream& out, X<T>& other)
{
for (int i = 0; i < other.index; i++)
out << i + 1 << ". " << other.collection[i];
return out;
}
int main()
{
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, n = sizeof(array)/sizeof(int);
X<int> x(n, array), b(x);
std::cout << x;
return 0;
}
Related
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 want to overload the stream insertion operator for a structure nested within a class. How can I fix this error and make the function to work, or is there any alternative method to implement it?
struct S {
int a;
int b;
};
class T {
private:
S** arrayName;
int r;
int c;
public:
friend ostream& operator << (ostream& _os, const T& _t) {
for (int i = 0; i < _t.r; i++) {
for (int j = 0; j < _t.c; j++) {
_os << _t.arrayName[i][j];
}
}
return _os;
}
}
If arrayName was just an integer array within class T like:
int arrayName [4][4]; //for example
the current implementation would work. But as arrayName is a pointer to pointer to struct S and acts as a two-dimensional array of struct S, you will need to overload the << operator within struct S to be able to print its members a and b.
So your struct S should now be:
struct S {
int a;
int b;
friend ostream& operator<<(ostream& _os, const S& _s) {
_os << _s.a << ' ' << _s.b << endl;
return _os;
}
};
I'm practicing templates in Visual Studio 2013 from a not so well written C++ book and I receive the following compiler errors respectively, "error C4430: missing type specifier - int assumed. Note: C++ does not support default-int" and "error C2143: syntax error : missing ',' before '<'".
Both refer me to line 10 which is...
std::ostream& operator<< (std::ostream&, const Array<T>&);
The desired behavior of my code is to show the creation and destruction of temporary Animal objects using templates.
The troubleshooting steps I have tried so far include substituting std::iostream& with int in my return type and first parameter type of line 10. After doing so the error messages remained the same. This seemed to suggest that the problem may be the second parameter type. I then added the keyword typename to the second parameter of my overloading operator function (operator<<) on line 10 and the error still persisted.
Line 10 can be found in the header file below.
//Array.h
#ifndef ARRAY_H
#define ARRAY_H
#include <iostream>
#include "Animal.h"
const int DefaultSize = 3;
template <typename T>
std::ostream& operator<< (std::ostream&, const Array<T>&);
template <typename T> // declare the template and the paramenter
class Array // the class being parameterized
{
public:
Array(int itsSize = DefaultSize);
Array(const Array &rhs);
~Array() { delete[] pType; }
// operators
Array& operator=(const Array&);
T& operator[](int offSet) { return pType[offSet]; }
const T& operator[](int offSet) const { return pType[offSet]; }
// accessors
int GetSize() const { return itsSize; }
// friend function
friend std::ostream& operator<< (std::ostream&, const Array<T>&);
private:
T *pType;
int itsSize;
};
template <typename T>
Array<T>::Array(int size = DefaultSize) :itsSize(size)
{
pType = new T[size];
for (int i = 0; i < size; i++)
pType[i] = static_cast<T>(0);
}
Array<Animal>::Array(int AnimalArraySize) :itsSize(AnimalArraySize)
{
pType = new Animal[AnimalArraySize];
}
template <typename T>
Array<T>::Array(const Array &rhs)
{
itsSize = rhs.GetSzie();
pType = new T[itsSize];
for (int i = 0; i < itsSize; i++)
pType[i] = rhs[i];
}
template <typename T>
Array<T>& Array<T>::operator=(const Array &rhs)
{
if (this == &rhs)
return *this;
delete[] pType;
itsSize = rhs.GetSize();
pType = new T[itsSize];
for (int i = 0; i < itsSize; i++)
pType[i] = rhs[i];
return *this;
}
template <typename T>
std::ostream& operator<< (std::ostream& output, const Array<T> &theArray)
{
for (int i = 0; i < theArray.GetSize(); i++)
output << "[" << i << "]" << theArray[i] << std::endl;
return output;
}
#endif
Here's the rest of my code from my book for your reference.
//Animal.h
#ifndef ANIMAL_H
#define ANIMAL_H
#include <iostream>
class Animal
{
public:
// constructors
Animal();
Animal(int);
~Animal();
// accessors
int GetWeight() const { return itsWeight; }
void SetWeight(int theWeight) { itsWeight = theWeight; }
// friend operators
friend std::ostream& operator<<(std::ostream&, const Animal&);
private:
int itsWeight;
};
#endif
//Animal.cpp
#include "Animal.h"
#include <iostream>
Animal::Animal() :itsWeight(0)
{
std::cout << "animal() ";
}
Animal::Animal(int weight) : itsWeight(weight)
{
std::cout << "animal(int) ";
}
Animal::~Animal()
{
std::cout << "Destroyed an animal...";
}
//Main.cpp
#include <iostream>
#include "Animal.h"
#include "Array.h"
std::ostream& operator<<(std::ostream&, const Animal&);
void IntFillFunction(Array<int>& theArray);
void AnimalFillFunction(Array<Animal>& theArray);
int main()
{
Array<int> intArray;
Array<Animal> animalArray;
IntFillFunction(intArray);
AnimalFillFunction(animalArray);
std::cout << "intArray...\n" << intArray;
std::cout << "\nanimalArray...\n" << animalArray << std::endl;
std::cin.get();
return 0;
}
std::ostream& operator<<(std::ostream& theStream, const Animal& theAnimal)
{
theStream << theAnimal.GetWeight();
return theStream;
}
void IntFillFunction(Array<int>& theArray)
{
bool Stop = false;
int offset, value;
while (!Stop)
{
std::cout << "Enter an offset (0-9) and a value. ";
std::cout << "(-1 to stop): ";
std::cin >> offset >> value;
if (offset < 0)
break;
if (offset > 9)
{
std::cout << "***Please use values between 0 and 9.***\n";
continue;
}
theArray[offset] = value;
}
}
void AnimalFillFunction(Array<Animal>& theArray)
{
Animal *pAnimal;
for (int i = 0; i < theArray.GetSize(); i++)
{
pAnimal = new Animal(i * 10);
theArray[i] = *pAnimal;
delete pAnimal;
}
}
I've tried my best to keep this question on topic by providing you with the desired behavior of the program, a specific problem or error and the shortest code necessary to reproduce it. All of which are requirements for debugging help as documented in the Help Center page.
I'm new to this website, and if my question is still off-topic, please let me know how I can change my question to be more on topic or inform me of a better place to ask my question. - Thank you
This function is declared before the Array class is declared (i.e., the compiler has never seen that type and doesn't know what it is, hence your error).
template<typename> class Array; // Add this forward declaration
template <typename T>
std::ostream& operator<< (std::ostream&, const Array<T>&);
Edit
I just noticed that the operator<< is declared before the Array class and as a friend function within the Array class. You could just remove the declaration at the top.
Edit 2
Array.h
I removed the following items
#include "Animal.h"
template <typename T>
std::ostream& operator<< (std::ostream&, const Array<T>&);
Array<Animal>::Array(int AnimalArraySize) :itsSize(AnimalArraySize)
{
pType = new Animal[AnimalArraySize];
}
Updated the friend function declartion to be
template<typename T> // This is not a member function so must be declared as a template
friend std::ostream& operator<< (std::ostream&, const Array<T>&);
Animal.h
This class has the friend function but it's not implemented in the cpp file. I moved the definition from the main.cpp into Animal.cpp
I am trying to build my own std::vector class but I am having trouble overloading the subscript ([]) and the cout << operators.
So far, I have tried to define the << operator as a public member of the class and then write the function's body outside the class declaration.
Right now I am getting terminal pages full of errors from iostream library and I do not even know where to begin looking through them.
I am a beginner in C++ and not accustomed to friend keyword or the template keyword. What am I doing wrong?
template<typename T>
class MyVector {
private:
T* Array;
public:
T& operator[](int b)
{
...
}
std::ostream& output(std::ostream& s) const;
};
std::ostream& operator<<(std::ostream& output, MyVector& A)
{
int i;
for(i = 0; i < A.GetDimension(); i++)
{
output << A[i] << " ";
}
output << "\n";
return output;
};
What you have is right, you just forgot the template declaration:
template <typename T>
std::ostream& operator<<(std::ostream& output, MyVector<T>& A)
{
int i;
for (i = 0; i < A.GetDimension(); i++)
{
output << A[i] << " ";
}
output << "\n";
return output;
};
template<typename T>
class MyVector{
...
std::ostream& printToStream(std::ostream& output) const {
int i;
for (i = 0; i < Dimension; i++) {
output << Array[i] << " ";
}
output << "\n";
return output;
}
...
};
template<typename T>
std::ostream& operator<<(std::ostream& output, const MyVector<T>& A) {
return A.printToStream(output);
}
I'm implementing a templated vector class (not the data container, but the vector in the linear algebra sense), and I'm getting quite a few errors whenever I refer to rhs in my operator overloading. Also, my copy constructor doesn't seem to be working.
#ifndef __VecXd__VecXd__
#define __VecXd__VecXd__
#define ULL unsigned long long
#include <iostream>
using namespace std;
template <class T>
class VecXd
{
public:
explicit VecXd(ULL newDimension = 1) { dimension = newDimension; vector = new T[newDimension];}
VecXd(const VecXd<T> &rhs);
VecXd<T>& operator=(const VecXd<T> &rhs);
const VecXd<T> operator+(const VecXd<T> &rhs) const;
VecXd<T>& operator+=(const VecXd<T> &rhs);
friend ostream& operator<<(ostream &out, VecXd<T> vec);
friend istream& operator>>(istream &in, VecXd<T>& vec);
~VecXd() { delete[] vector; }
const ULL getDimension() { return dimension; }
const T itemAtIndex(ULL index) { if(index >= dimension) throw 1; return vector[index]; }
private:
ULL dimension;
T *vector;
};
template <class T>
VecXd<T>::VecXd(const VecXd<T> &rhs)
{
dimension = rhs.getDimension();
vector = new T[dimension];
for (ULL i = 0; i < dimension; ++i)
vector[i] = rhs.itemAtIndex(i);
}
template <class T>
VecXd<T>& VecXd<T>::operator=(const VecXd<T> &rhs)
{
if (this != &rhs)
{
if (dimension != rhs.getDimension())
{
delete [] vector;
dimension = rhs.getDimension();
vector = new T[dimension];
}
for (ULL i = 0; i < dimension; ++i)
vector[i] = rhs.itemAtIndex(i);
}
return *this;
}
template <class T>
VecXd<T>& VecXd<T>::operator+=(const VecXd<T> &rhs)
{
if (dimension != rhs.getDimension())
{
cout << "\nCannot perform addition. Vectors do not have the same dimensions.\n";
throw 1;
}
else
{
for (ULL i = 0; i < dimension; ++i)
vector[i] += rhs[i];
}
return *this;
}
template <class T>
const VecXd<T> VecXd<T>::operator+(const VecXd<T> &rhs) const
{
VecXd<T> temp = *this;
temp += rhs;
return temp;
}
template <class T>
ostream& operator<<(ostream &outs, VecXd<T> vec)
{
for (ULL i = 0; i < vec.dimension; ++i)
out << vec.vector[i] << (i+1 < vec.dimension ? " " : "");
return out;
}
template <class T>
istream& operator>>(istream &in, VecXd<T> &vec)
{
ULL newDim = 1;
cin >> newDim;
if (!cin.good())
{
cout << "\nImproper input.\n";
throw 1;
}
else
{
delete [] vec.vector;
vec.dimension = newDim;
vec.vector = new T[vec.dimension];
for (ULL i = 0; i < vec.dimension; ++i)
in >> vec.vector[i];
}
return in;
}
#endif /* defined(__VecXd__VecXd__) */
I'm getting errors of this style:
Member function 'getDimension' not viable: 'this' argument has type 'const VecXd<int>', but function is not marked const
This happens every time rhs calls a function (such as getDimension() or itemAtIndex()); two error appear (once for VecXd<int> and another for VecXd<int>).
Also, the copy constructor is not recognized in the overloaded +operator function in this line:
VecXd<T> temp = *this;
Help?
To be able to call a function on a const object, you need to promise the compiler that the function will not modify the object. To do that, you mark the function with the keyword const after its argument list. For example, to make getDimension a const member function, you would change it to:
const ULL getDimension() const { return dimension; }
(Note that the const in the return type will have absolutely no effect, so you should get rid of it)