agarrow
agarrow

Reputation: 457

trouble defining template classes, operators, and iterators

So I'm trying to define a template class "TwoWayVector" and "TwoWayVectorIterator" but I've been running into a lot of problems. I want to define == within TwoWayVector to return a reference and take as a parameter a const TwoWayVector, this is how I've defined my other operators and g++ hasn't complained, but for some reason the code below produces the errors

TwoWayVector.cc: In member function ‘bool& TwoWayVector<T>::operator==(TwoWayVector<T>)         [with T = int]’:
Test.cc:10:   instantiated from here
TwoWayVector.cc:40: error: passing ‘const TwoWayVector<int>’ as ‘this’ argument of ‘T&       TwoWayVector<T>::operator[](int) [with T = int]’ discards qualifiers
Test.cc:10:   instantiated from here
TwoWayVector.cc:32: warning: reference to local variable ‘result’ returned

Test.cc

#include <iostream>
#include "TwoWayVector.cc"
int main(){
TwoWayVector<int> numbers;
TwoWayVector<int> numbers2;
numbers.push_back(3);
numbers.push_back(2);
numbers2.push_back(3);
numbers2.push_back(2);
cout << (numbers==numbers2);
cout << endl;
return 0;
}

TwoWayVector.cc

using namespace std;
#include "TwoWayVectorIterator.cc"
template <class T> class TwoWayVector{
public:

T* data;
int capacity;
int nextFree;

TwoWayVector(){
    capacity = 10;
    nextFree = 0;
    data = new T[capacity];
}

~TwoWayVector(){
    delete data;
}

T& operator[](const int index){
    if( index >= capacity || capacity + index < 0){
        string number = static_cast<ostringstream*>( &(ostringstream() << index) )->str();
        string error = "index " + number + " is out of bounds";
        throw error;
    }
    else if(index < 0){
        return data[nextFree+index];
    }
    return  data[index];
}
bool& operator==(const TwoWayVector vector2){
    bool result = true;
    if(capacity != vector2.capacity){
        result = false;
    }
    if(nextFree != vector2.nextFree){
        result = false;
    }
    for(int i=0; i<nextFree ; i++){
        if(data[i] != vector2[i]){
            result = false;
        }
    }
    return result;
}
 //memory leaks?
void push_back(T object){
    if(capacity <= nextFree){
        capacity = capacity*2;
        T* tmp = new T[capacity];
        for(int i=0; i<capacity; i++){
            tmp[i] = data[i];
        }
        delete data;
        data = tmp;
    }
    data[nextFree] = object;
    nextFree++;
}

T pop_back(){
    nextFree--;
    T result = data[nextFree];
    data[nextFree] = NULL;
    return result;
}

int size(){
    return nextFree;
}

TwoWayVectorIterator<T>* begin(){
    TwoWayVectorIterator<T>* i = new TwoWayVectorIterator<T>(0,this);
    return (i);
}
TwoWayVectorIterator<T>* end(){
    TwoWayVectorIterator<T>* i = new TwoWayVectorIterator<T>(nextFree,this);
    return(i);
}

};

TwoWayVectorIterator.cc

#include <sstream>

using namespace std;

template<typename T> class TwoWayVector;

template <class T> class TwoWayVectorIterator{
public:
TwoWayVector<T>* vector;
int currentPosition;
TwoWayVectorIterator(TwoWayVector<T>& vec){
    currentPosition = 0;
    vector = vec;
}
TwoWayVectorIterator( int pos , TwoWayVector<T>* vec){
    currentPosition = pos;
    vector = vec;
}

bool& operator==(const TwoWayVectorIterator vector2){
    bool contents, position;
    contents = (vector == vector2) ? true : false;
    position =(currentPosition == vector2->currentPosition) ? true : false;
    return (contents && position);
}

bool& operator!=(const TwoWayVectorIterator vector2){
    bool contents, position;
    contents = (vector == vector2) ? false : true;
    position=(currentPosition == vector2->currentPosition) ? false : true;
    return (contents || position);
}

TwoWayVectorIterator& operator++(){
    return *this;
    currentPosition = (currentPosition+1);

}
TwoWayVectorIterator& operator++(int){
    currentPosition = (currentPosition+1);
    return *this;
}
TwoWayVectorIterator& operator=(TwoWayVectorIterator* vector2){
    &vector = vector2;
    currentPosition = vector2->currentPosition;
    return *this;
}
TwoWayVectorIterator& operator+(int n){
    currentPosition = currentPosition+n;
    return *this;
}
TwoWayVectorIterator& operator-(int n){
    currentPosition = currentPosition-n;
    return *this;
}
bool& operator<(TwoWayVectorIterator* vector2){
    return (currentPosition<vector2->currentPosition);
}
T& operator*(){
    return vector[currentPosition];
}
};

If I change the == operator definition in TwoWayVector.cc to

bool operator==(TwoWayVector vector2){
    bool result = true;
    if(capacity != vector2.capacity){
        result = false;
    }
    if(nextFree != vector2.nextFree){
        result = false;
    }
    for(int i=0; i<nextFree ; i++){
        if(data[i] != vector2[i]){
            result = false;
        }
    }
    return result;
}

Then everything compiles, but when I run it I get

1
a.out(40908) malloc: *** error for object 0x7fe4f2c03b40: pointer being freed was not   allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

any ideas?

Upvotes: 1

Views: 124

Answers (2)

alexrider
alexrider

Reputation: 4463

Basically crash happends due to lack of copy constructor. See rule of three. When

bool operator==(TwoWayVector vector2){

Is used in main, there is copy of vector created, holding pointers from numbers2, then on exit form operator ==, copy is deleted, leaving numbers2 with pointers to already freed memory, that it attempts to delete on exit of main(), that leads to error.

Upvotes: 1

Detheroc
Detheroc

Reputation: 1921

Inside operator== you call operator[], which is non-const, on a const variable, vector2.

You should add an alternative read-only version of the operator:

const T & operator[](const int index) const;

But you should use a reference for the object parameter like this:

bool operator==(const TwoWayVector &vector2) const;

Otherwise, the const keyword doesn't really do much because it only says that your copy of the object, which was just created on the stack for the function cannot be modified, which doesn't really matter. (So the easiest way to fix this would be to remove the const keyword from vector2 but it isn't exatly correct.)

And, of course, don't return the bool value as a reference, because it references the variable result, which will no longer exist as soon as you leave the function.

Upvotes: 2

Related Questions