2

I am trying to create my own vector class. Currently, im working on adding an erase function to my vector class called, Vec. My code complains when i pass variable.begin() into the erase function parameter but function properly after i manually converted variable.begin() into iterator then pass it in.

Can someone explain to me why this bizarre situation is occuring?

int main(){
    Vec<string> words;

    words.push_back("h");
    words.push_back("a");
    words.push_back("p");

    Vec<string>::iterator iter=words.begin();
    Vec<string>::iterator iter1=words.end();
    words.erase(words.begin(),words.end());//this does not work
    words.erase(iter,iter1);//this works
}
//Function erase in the Vec class i created


template <class T> class Vec {

    typedef T* iterator;//
    typedef const T* const_iterator;
    iterator data; // first element in the Vec
    iterator avail; // (one past) the last element in the Vec
    iterator limit; // (one past) the allocated memory

    void erase(iterator&i, iterator&j){
        iterator new_limit=limit;
        iterator new_avail=avail;
        size_t a=j-i+1;
        size_t n=limit-data;
        n=n-a;
        iterator new_data=alloc.allocate(n);

        iterator mid=std::uninitialized_copy(data,data+1,new_data);
        size_t b=size();
        if(j!=avail){
            new_limit, new_avail=std::uninitialized_copy(j+1,avail,mid);
            data=new_data;
            avail=new_avail;
            limit=new_limit;
        }
        else{
            data=new_data;
            limit=avail=data+n;
        }
    }
}
mch
  • 9,424
  • 2
  • 28
  • 42
Esther
  • 47
  • 3
  • You can change your `erase` function to get the iterators by value. I have no idea if this is the best way to do this. – mch Aug 01 '17 at 08:57
  • May i ask how do i change that? Other than that, words.begin() is an iterator which is evident because i can assign it into Vec::iterator. So if thats the case, why wont erase accept my words.begin() as an iterator?? – Esther Aug 01 '17 at 09:02
  • How have you defined `begin` and `end` in your class? – Bob__ Aug 01 '17 at 09:05

2 Answers2

3

The definition void erase(iterator&i, iterator&j) is rather suspect.

iterator& means that you have to have an existing variable to bind to the (non-const) reference. Iterators are by design "pointer-equivalents", which would normally be passed by value. You wouldn't write void erase(string*&i, string*&j).

The easiest solution is to change erase to void erase(iterator i, iterator j)

Also you haven't "converted" anything to an iterator. You have assigned an iterator value to an iterator variable. The compiler is complaining about the value-category of the expressions involved.

Caleth
  • 52,200
  • 2
  • 44
  • 75
0

To understand why it does not work take this example:

void test(int& r)
{
}

int a = 42;
test(a);

a is an lvalue and can be bound to a non-const reference.

On the other hand, the value returned from the following func() is a temporary and this can only be bound to a constant reference, value, or rvalue reference.

int func() { return 42; }

test(func()); // error

To make it work you'd have to either assign the return value of func() to an lvalue, or change the test() function to take a constant reference.

a = func();
test(a);

or

void test(int const & r)
{
}

test(func());

Now, substitute erase() for test() and begin()/end() for func() and you should have the answer why it does not work.

Your erase() function does not look right. It should take constant iterators and instead return an iterator (past the last removed element or end if the vector is empty after erasing).

iterator erase(const_iterator first, const_iterator last);
Marius Bancila
  • 16,053
  • 9
  • 49
  • 91