Templates and operator overloading

#include <iostream>
using namespace std;

const int DefaultSize = 10;

class Animal
{
public:
Animal(int);
Animal();
~Animal(){}
int GetWeight() const {return itsWeight;}
void Display() const {std::cout << itsWeight;}
private:
int itsWeight;
};

Animal::Animal(int weight):itsWeight(weight)
{}

Animal::Animal():itsWeight(0)
{}

template <class T>
class Array
{
private:
T* pType;
int itsSize;

public:
Array(int itsSize = DefaultSize);
Array(const Array &rhs);
~Array(){delete [] pType;}

Array& operator=(const Array&);
T& operator[](int offset){ return pType[offset];}
const T& operator[](int offset) const
{ return pType[offset];}
int GetSize() const {return itsSize;}

};

template <class T>
Array<T>::Array(int size):itsSize(size)
{
pType = new T[size];
}

template <class T>
Array<T>::Array(const Array &rhs)
{
itsSize = rhs.GetSize();
pType = new T[itsSize];
for (int i=0; i<itsSize; i++)
{
pType[i] = rhs[i];
}
}

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

int main()
{
Array<int> theArray;
Array<Animal> theZoo;
Animal *pAnimal;

for(int i=0; i<theArray.GetSize(); i++)
{
theArray[i] = i*2;
pAnimal = new Animal(i*3);
theZoo[i] = *pAnimal;
delete pAnimal;
}

for(int j=0; j<theArray.GetSize(); j++)
{
std::cout << "theArray[" << j << "]:\t";
std::cout << theArray[j] << "\t\t";
std::cout << "theZoo[" << j << "]:\t";
theZoo[j].Display();
std::cout << std::endl;
}
return 0;
}

This is a working program showcasing use of templates and operator overloading. In the main program, if line:
theZoo[i] = *pAnimal; is replaced by:
theZoo[i] = pAnimal;

and if an overloaded template function for operator = is added like this:

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

Here the template takes pointer to Array as argument and accesses value at that pointer location to copy each element of array.

The program gives compilation error: binary '=' : no operator defined which takes a right-hand operand of type 'class Animal *' (or there is no acceptable conversion)

What I couldn't understand is this - if theZoo[i] = *pAnimal works fine along with its template function, why couldn't theZoo[i] = pAnimal work with its corresponding template function?

Any hints are appreciated. Thanks in advance.
You would need to implement

operator=( const Animal* rhs );

on class Animal, because the expression "theZoo[x]" has type Animal, not Array.
Thanks for the reply jsmith.

Can you please tell me how exactly to decide the class for operator=(), in both these cases?

1) theZoo[i] = *pAnimal - correct working is, it should be in template Array
2) theZoo[i] = pAnimal - you said it should be in class Animal

Thanks.
What is the type of theZoo[i]? It is Animal, correct? (You've implemented operator[] on Array to return a T& where T=Animal).

Then Animal::operator=() is called with the rvalue as parameter. The rvalue in case #1 is *pAnimal which has type Animal. In case #2 it is Animal*.

In general, in the expression x = y where x has type X and y has type Y, X::operator=( const Y& ) is invoked.
I tried the program and found that the second case will work if an array of pointer to Animal is declared like this:

Array<Animal*> theZoo;

So I think I have understood it now. Thanks a lot.

Topic archived. No new replies allowed.