Hey guys, new poster here. I'm rather desperate here, I just do not understand the concept of templates very well. I've used the search function, but I don't see the problem addressed in any other threads. Any help is much appreciated.

My assignment is to create a templated vector class using the following prototypes/definitions:
//I cannot modify these prototypes at all.

#ifndef _MYVECTOR
#define _MYVECTOR
#include <iostream>
using namespace std;

class BADINDEX{};

template <class T>
class containerInterface
{
    public:
        virtual containerInterface <T>& pushFront(T)  = 0;
        virtual containerInterface <T>& pushBack(T)   = 0;
        virtual containerInterface <T>& popFront(T&) throw(BADINDEX) = 0;
        virtual containerInterface <T>& popBack(T&)  throw(BADINDEX) = 0;
        virtual int getSize()      = 0;
        virtual bool isFull()      = 0;
        virtual bool isEmpty()     = 0;
        virtual T front()    throw(BADINDEX)   = 0;
        virtual T back()     throw(BADINDEX)   = 0;
        virtual T& operator[] (int) throw(BADINDEX)  = 0;
        virtual void erase()    throw(BADINDEX) = 0;
};

template <class T>
class myVector:public containerInterface<T>
{
    public:
        myVector();
        ~myVector();
        myVector(const myVector&);
        myVector <T>& operator=(myVector&);
        myVector <T>& pushFront(T);
        myVector <T>& pushBack (T);
        myVector <T>& popFront (T&)  throw(BADINDEX);
        myVector <T>& popBack  (T&)  throw(BADINDEX);
        T front()  throw(BADINDEX);
        T back()   throw(BADINDEX);
        T& operator[] (int) throw(BADINDEX);
        int getSize();
        bool isFull();
        bool isEmpty();
        void erase();

    private:
        T *data;
        int size;
        int capacity;
        void grow();
        void shiftRight();
        void shiftLeft();
};

I think I understand how to do it, and have written all the functions, but it will not compile, and I think my constructor, copy constructor, and destructor are the primary culprits, since they do not have a bracketed <T> as part of the function header. Here are the functions I've written:

myVector::myVector()
{
    size = 0;
    capacity = 10;

    data = new T [capacity];

}

myVector::~myVector()
{
    delete [] data;
}

myVector::myVector(const myVector& other)
{
    size = other.size;
    capacity = other.capacity;

    data = new T [capacity];

    for(int i = 0; i < size; i++)
    {
        data[i] = other.data[i];
    }
}

myVector<T>& myVector::operator=(myVector& other)
{
    if(data != other.data)
    {
        delete[] data;
        size = other.size;
        capacity = other.capacity;

        data = new T [capacity];

        for(int i = 0; i < size; i++)
        {
            data[i] = other.data[i];
        }
    }

    return *this;
}

myVector<T>& myVector::pushFront(T n)
{
    shiftRight();
    data[0] = n;

    return *this;
}

myVector<T>& myVector::pushBack(T n)
{
    size++;
    grow();

    data[size] = n;

    return *this;
}

myVector<T>& myVector::popFront(T& n)
{
    n = data[0];

    shiftLeft();

    return *this;
}

myVector<T>& myVector::popBack(T& n)
{
    n = data[size];

    size--;

    return *this;
}

T front()
{
    return data[0];
}

T back()
{
    return data[size];
}

T& operator[](int n)
{
    return data[n];
}

int getSize()
{
    return size;
}

bool isFull()
{
    return (size == capacity);
}

bool isEmpty()
{
    bool answer = false;

    if(size == 0)
    {
        answer = true;
    }

    return answer;
}

void erase()
{
    delete []data;

    size = 0;
    capacity = 10;

    data = new T [capacity];
}

void grow()
{
    while(size >= capacity)
    {
        T* temp;
        temp = data;

        capacity *= 2;

        data = new T[capacity];

        for(int i = 0; i < size; i++)
        {
            data[i] = temp.data[i];
        }

        delete []temp;
    }

}

void shiftRight()
{
    size++;
    grow();

    for(int i = size; i > 0; i--)
    {
        data[i] = data[i - 1];
    }
}

void shiftLeft()
{
    size--;

    for(int i = 0; i < size; i++)
    {
        data[i] = data[i + 1];
    }
}

I get a compile error on the line of the constructor telling me that I can't use the template class myVector without template parameters. This makes sense, but I don't know how to fix it. Any help is appreciated. Thanks.

Dani AI

Generated

Short expert summary: the original compile problem was just the familiar template rule — each out‑of‑class member definition must be introduced with the template parameter list and the class name must be written with its parameters. pointed this out; that change explains why compilation proceeded once the headers were added. The remaining failures in the thread were logical/runtime issues rather than template syntax.

Common logical pitfalls that remained (and how they tend to manifest):

  • Off‑by‑one indexing for the “last” element. The last valid index is size−1; reads/writes at size will go out of bounds and cause odd behavior. That impacts back, popBack, and any code that increments size before storing.
  • Bounds checking should test against current size, not capacity; checking capacity lets an out‑of‑range access slip through.
  • Resizing/copying the buffer: when replacing the array, copy from the old pointer with simple old[i], then delete[] old. ’s observation about temp being a pointer is exactly the right diagnosis for the copy error.
  • Shift/resize helpers must update size in the correct order (and avoid underflow when popping an empty container).

Design and safety recommendations:

  • Implement the rule of three correctly: copy constructor, assignment operator (take a const reference), and destructor. Use a self‑assignment check (or better, the copy‑and‑swap idiom) so assignment is exception‑safe: allocate a new buffer first, then swap and delete the old buffer. That prevents leaks if allocation throws.
  • Prefer unsigned size_t for counts, initialize members in an initializer list, and consider RAII (std::vector or smart pointers) for real code. Note that dynamic exception specifications like throw(BADINDEX) are legacy; modern code uses noexcept or standard exceptions.

Quick tests that catch these bugs: push until growth triggers, pop until empty, copy and self‑assign, and chain operations (the driver’s v1.pushBack(i).pushFront(-i)). The thread shows the core issues were fixed step by step — credit to and , and to for resolving the final logic error.

Recommended Answers

All 5 Replies

If you define a member function for a template class outside of the class definition, you need to recreate the template parameters:

template <typename T>
myVector<T>::myVector()
{
    size = 0;
    capacity = 10;

    data = new T [capacity];

}

template <typename T>
myVector<T>::~myVector()
{
    delete [] data;
}

Thanks, Narue, that was helpful. That solved most of my problems, and I figured out some of the exception handling issues that I had as well. I think something is still fundamentally wrong, as I am getting the following errors.

#ifndef _MYVECTOR
#define _MYVECTOR
#include <iostream>
using namespace std;

class BADINDEX{};

template <class T>
class containerInterface
{
    public:
        virtual containerInterface <T>& pushFront(T)  = 0;
        virtual containerInterface <T>& pushBack(T)   = 0;
        virtual containerInterface <T>& popFront(T&) throw(BADINDEX) = 0;
        virtual containerInterface <T>& popBack(T&)  throw(BADINDEX) = 0;
        virtual int getSize()      = 0;
        virtual bool isFull()      = 0;
        virtual bool isEmpty()     = 0;
        virtual T front()    throw(BADINDEX)   = 0;
        virtual T back()     throw(BADINDEX)   = 0;
        virtual T& operator[] (int) throw(BADINDEX)  = 0;
        virtual void erase()    = 0;
};

template <class T>
class myVector:public containerInterface<T>
{
    public:
        myVector();
        ~myVector();
        myVector(const myVector&);
        myVector <T>& operator=(myVector&);
        myVector <T>& pushFront(T);
        myVector <T>& pushBack (T);
        myVector <T>& popFront (T&)  throw(BADINDEX);
        myVector <T>& popBack  (T&)  throw(BADINDEX);
        T front()  throw(BADINDEX);
        T back()   throw(BADINDEX);
        T& operator[] (int) throw(BADINDEX);
        int getSize();
        bool isFull();
        bool isEmpty();
        void erase();

    private:
        T *data;
        int size;
        int capacity;
        void grow();
        void shiftRight();
        void shiftLeft();
};

template <class T>
myVector<T>::myVector()
{
    size = 0;
    capacity = 10;

    data = new T [capacity];

}

template <class T>
myVector<T>::~myVector()
{
    delete [] data;
}

template <class T>
myVector<T>::myVector(const myVector& other)
{
    size = other.size;
    capacity = other.capacity;

    data = new T [capacity];

    for(int i = 0; i < size; i++)
    {
        data[i] = other.data[i];
    }
}

template <class T>
myVector<T>& myVector<T>::operator=(myVector& other)
{
    if(data != other.data)
    {
        delete[] data;
        size = other.size;
        capacity = other.capacity;

        data = new T [capacity];

        for(int i = 0; i < size; i++)
        {
            data[i] = other.data[i];
        }
    }

    return *this;
}

template <class T>
myVector<T>& myVector<T>::pushFront(T n)
{
    shiftRight();
    data[0] = n;

    return *this;
}

template <class T>
myVector<T>& myVector<T>::pushBack(T n)
{
    size++;
    grow();

    data[size] = n;

    return *this;
}

template <class T>
myVector<T>& myVector<T>::popFront(T& n) throw(BADINDEX)
{
    if(size > 0)
    {
        n = data[0];

        shiftLeft();
    }
    else
    {
        throw BADINDEX();
    }
    return *this;
}

template <class T>
myVector<T>& myVector<T>::popBack(T& n) throw(BADINDEX)
{

    if(size > 0)
    {
        n = data[size];

        size--;
    }
    else
    {
        throw BADINDEX();
    }
    return *this;
}

template <class T>
T myVector<T>::front() throw(BADINDEX)
{
    if(size > 0)
    {
        return data[0];
    }
    else
    {
        throw BADINDEX();
    }
}

template <class T>
T myVector<T>::back() throw(BADINDEX)
{
    if(size > 0)
    {
        return data[size];
    }
    else
    {
        throw BADINDEX();
    }
}

template <class T>
T& myVector<T>::operator[](int n) throw(BADINDEX)
{
    if(n >= capacity || n < 0)
    {
        throw BADINDEX();
    }
    else
    {
        return data[n];
    }
}

template <class T>
int myVector<T>::getSize()
{
    return size;
}

template <class T>
bool myVector<T>::isFull()
{
    return (size == capacity);
}

template <class T>
bool myVector<T>::isEmpty()
{
    bool answer = false;

    if(size == 0)
    {
        answer = true;
    }

    return answer;
}

template <class T>
void myVector<T>::erase()
{
    delete []data;

    size = 0;
    capacity = 10;

    data = new T [capacity];
}

template <class T>
void myVector<T>::grow()
{
    while(size >= capacity)
    {
        T* temp;
        temp = data;

        capacity *= 2;

        data = new T[capacity];

        for(int i = 0; i < size; i++)
        {
            data[i] = temp.data[i];
        }

        delete []temp;
    }

}

template <class T>
void myVector<T>::shiftRight()
{
    size++;
    grow();

    for(int i = size; i > 0; i--)
    {
        data[i] = data[i - 1];
    }
}

template <class T>
void myVector<T>::shiftLeft()
{
    size--;

    for(int i = 0; i < size; i++)
    {
        data[i] = data[i + 1];
    }
}

#endif

I get the following errors:


What it refers to as line 127 is line 118 in what I've pasted here, and what it refers to as line 256 is line 247 here.


The line it is referring to in the driver is:

for(int i = 0; i < 10; i++)
                   v1.pushBack(i).pushFront(-i);


Please advise. Thanks again. I really have no idea what those errors mean.

what it actually does.
Let me tell you what it actually does, and what it should do
first what it does

template <class T>
void myVector<T>::grow(){    
   while(size >= capacity)    {        
        T* temp;        
        temp = data;         
        capacity *= 2;         
        data = new T[capacity];         
        for(int i = 0; i < size; i++)        
        {
             data[i] = temp.data[i];        
        }
         delete []temp;    
  }
}

basically T refers to int in your case now the new code becomes.

void myVector<int>::grow(){    
   while(size >= capacity)    {        
        int* temp;        
        temp = data;         
        capacity *= 2;         
        data = new int[capacity];         
        for(int i = 0; i < size; i++)        
        {
             data[i] = temp.data[i];        
        }
         delete []temp;    
  }
}

lets move from bottom up manner you'll recognise yourself.
what does your sentence data = temp.data means ???
int is a primitive type not a aggregate type, so a compile error is there.
now you know what should be change.

Yeah, I found that last night, thanks. temp is a pointer, not an object, so I just needed to change temp.data to temp and it worked.

I have some sort of small logic error with popback and popfront, but everything else works fine.

Thanks for your help.

Figured out my last logic error. Solved. Thanks!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.