How to overload the << operator? - c++

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);
}

Related

Overload the stream insertion operator for nested structures/classes

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;
}
};

Invoking specialized ostream operator

I have the following code...
#include <sstream>
enum class eTag
{
A,
B,
C
};
template<eTag I> std::ostream& operator<< (std::ostream& str, int i)
{
return str; // do nothing
}
template<> std::ostream& operator<< <eTag::A>(std::ostream& str, int i)
{
return str << "A:" << i; // specialize for eTag::A
}
template<> std::ostream& operator<< <eTag::B>(std::ostream& str, int i)
{
return str << "B:" << i; // specialize for eTag::B
}
template<> std::ostream& operator<< <eTag::C>(std::ostream& str, int i)
{
return str << "C:" << i; // specialize for eTag::C
}
int main()
{
std::ostringstream s;
// s << <eTag::A>(42) << std::endl;
return 0;
}
This compiles. But as you can see from the commented line in main(), I'm struggling with how to actually invoke a specialization of the ostream operator.
Quick answer:
operator<< <eTag::A>(std::cout,42);
I think you're much better off with implementing your own template-class manipulator that friends ostream& operator<<(ostream&), and keeps the state as a member variable (initialized via a constructor). See here (except for the template-part)
operator<<<eTag::A>(std::cout, 42) << std::endl;
(You can add a space between operator<< and the template argument list if you want. Doesn't make a difference.)
This is pretty nasty. Usually we don't write operators that require explicit template arguments. Better to do something like this:
inline std::ostream& operator<<(std::ostream& os, eTag x) {
if (x == eTag::A) {
return os << "A:";
} else if (x == eTag::B) {
return os << "B:";
} else if (x == eTag::C) {
return os << "C:";
} else {
throw std::range_error("Out of range value for eTag");
}
}
Then:
std::cout << eTag::A << 42 << std::endl;
A good compiler will be able to inline this, so your code will be as efficient as if you had just typed
std::cout << "A:" << 42 << std::endl;

When using templates, how do I fix the following compiler error to achieve the desired behavior of my program?

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

Left of '.size' must have class/struct/union

Still cannot get this one to work. Please help!
template <typename T>
class Container{
public:
...
friend ostream& operator<<(ostream& ostr, const Container<T>& C)
{
for(size_t i=0; i!= data.size(); i++) // ERROR
ostr<<data[i]<<" ";
return ostr;
}
private:
vector<T> data;
};
data is a member of C and should therefore be accessed as C.data (remember that your operator<< is a free function and not a member of Container):
for(size_t i = 0; i != C.data.size(); ++i)
ostr << C.data[i] << " ";

"invalid use of non-static data member" when accessing a templated class' field through befriended output operator

I get the following error when I try to access a templated class'es field through befriended output operator.
Database.hpp: In function ‘std::ostream& ostream(std::ostream&, const Table<T, S>&)’:
Database.hpp:10:12: error: invalid use of non-static data member ‘Table<T, S>::tab’
Database.hpp:41:19: error: from this location
Database.hpp: In function ‘std::ostream& operator<<(std::ostream&, const List&)’:
Database.hpp:62:17: error: no match for ‘operator<<’ in ‘os << l.List::AnnouncementDate’
here is the exact code I wrote:
template <class T, int S>
class Table
{
T tab[S];
public:
inline T& operator[](int i)
{
return tab[i];
}
inline const T& operator[](int i) const
{
return tab[i];
}
Table() {}
~Table() {}
Table(const Table &t)
{
for ( int i=0; i<S; ++i )
{
tab[i] = t[i];
}
}
Table& operator=(const Table &t)
{
for ( int i=0; i<S; ++i )
{
tab[i] = t[i];
}
return *this;
}
friend std::ostream& ostream( std::ostream& os, const Table<T,S> &t )
{
for ( int i=0; i<3; os << '-' )
{
os << tab[i++];
}
return os;
}
};
typedef Table<int,3> Date;
struct List
{
Date AnnouncementDate;
int BonusShares;
int StockSplit;
int CashDividend;
bool DividendPayment;
Date ExDividendDate;
Date ShareRecordDate;
Date BonusSharesListingDate;
friend std::ostream& operator<<( std::ostream& os, const List &l )
{
os << l.AnnouncementDate << ',' << std::endl <<
l.BonusShares << ',' << std::endl <<
l.StockSplit << ',' << std::endl <<
l.CashDividend << ',' << std::endl <<
l.DividendPayment << ',' << std::endl <<
l.ExDividendData << ',' << std::endl <<
l.ShareRecordDate << ',' << std::endl <<
l.BonusSharesListingDate << ',' << std::endl;
return os;
}
};
typedef std::vector<List> Database;
Looks like you meant to name the friend function operator<< instead of ostream:
friend std::ostream& operator<<( std::ostream& os, const Table<T,S> &t )
// ^^^^^^^^^^
You'll also need to access tab as a member of t:
os << t.tab[i++];
This is because, although you defined the friend function inside your class definition, it has namespace scope:
A friend function defined in a class is in the (lexical) scope of the class in which it is defined.