hello all.

This program is just a collection of functions to demonstrate various programming principles. What I'm
saying is that don't worry about the overall function-it ain't all that...

One of the principles is using a 'non member' friend function to display the output.
I added this to the public functions and it's definition appears just below the class declaration.

I get warning about it's status (OK), but then the fatal error is

templ2.cpp: undefined reference to `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Array<int>&)'

the source:

// Implementation of the Template Array
#include <iostream>
using namespace std;
const int DefaultSize =10;

//declare a simple Animal class so that we can create an
//array of animals

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> //declare the template and the parameter
class Array       // the class being paramterized
{
    public:
        //costrucyors
        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;}
        //template <class T>//compiler needs this if non member friend
        friend ostream& operator << (ostream&, Array<T>&);
        
    
        
    private :
        T *ptype;
        int itsSize;
};

template <class T>
ostream& operator << (ostream& output, Array<T>& theArray)
{
    for (int i = 0; i < theArray.itsSize; i++)
      output << "[" << i << "]" << theArray[i] <<endl;
    
    return output;
}

//implementations follow...

//implement the constructor
template <class T>
Array<T>::Array(int size):
itsSize(size)
{
    ptype = new T[size];
    //the constructors of the type created
    //should be of default value
}

//copy constructor
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];
}
//operator=

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

//driver program

int main()

{
    bool Stop = false;  //looping flag
    int offset , value;
    Array<int> theArray;
    while (Stop = false)
    {
        cout << "Enter an offset (0-9)";
        cout << "and a value. (-1 to stop): ";
        cin >> offset >>value;

        if (offset < 0 )
            break;
        if (offset > 9)
        {
            cout << "*** Please use values between 0 and 9. ***\n";
            continue;
        }
        theArray[offset] = value;
    }
    cout << "\nHere's the entire array:\n";
    cout << theArray << endl;
            
    return 0;
}

I'm sure you eagle -eyed pro's can spot the problem in a New York minute, but I've been straring at this too long!

Thanks in advance!

My solution would be to write a public get function and use it in the loop instead of attempting to accessing the private member directly.

I'm sure you eagle -eyed pro's can spot the problem in a New York minute, but I've been straring at this too long!

I don't blame you, since what you encountered is one of the C++ gotchas and not many starters know about it.

What you are trying to do here is to create a function which will befriend all the specializations of the Array class, which I don't think any compiler conforming with the standards will allow you to do.

There are some things which you have to do to get around this...

1. Forward declare the class, along with the templated overloaded function.

template <class T> 
class Array ;
template <class T>
ostream& operator<< ( ostream&, Array<T>& ) ;

2. Place <> after the overloaded operator to let the compiler know that this is a templated funcion you are tryign to code here (syntactic sugar...bleh). Something like:

template <class T> //declare the template and the parameter
class Array       // the class being paramterized
{
    public:
        ....
        friend ostream& operator<< <>(ostream&, Array<T>&);
    private :
        ....
};

For an interesting read look here.

Comments
Nice~~SunnyPalSingh

Yep! That's the way it works. Seems like alot of trouble to make the direct acess friend function to compile.

here's the final draft that compiles using the friend function.
Note that the template id operator <> is only used where is declared as a public function. The definition doesn't need it. That rather surprises me...

template <class T >
class Array;

template <class T>
ostream& operator << (ostream& , Array<T>& );
template <class T> //declare the template and the parameter
class Array       // the class being paramterized


{
    public:
        //costrucyors
        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 ostream& operator << <> (ostream&, Array<T>&);



    private :
        T *ptype;
        int itsSize;
};


template <class T >
ostream& operator << (ostream& output, Array<T>& theArray)


{
    for (int i = 0; i < theArray.itsSize; i++)
      output << "[" << i << "]" << theArray[i] <<endl;

    return output;
}

Thanks for your input!

This question has already been answered. Start a new discussion instead.