Error using vector::erase()

I keep getting the error: no matching function for call to `std::vector<Menu_Item, std::allocator<Menu_Item> >::erase(int&)'


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int item;

	cout << "Please enter the menu item id you want to delete: \n";
	cin >> item;

	for (int i = 0; i < menu_items.size(); i++)
	{
		if(item==menu_items[i].item_id())
		{
			found = true;
			Menu::menu_items.erase(i);
		}
		else
		{
			cout << "The ID number entered is wrong, please try again.\n";
		}
	}
	}


What am I doing wrong? My vector is in Menu.h, which is called by Menu.cpp, which is run in my main().
std::vector::erase takes an iterator, not an int. You'll have to get an iterator somehow if you want to use it.
1
2
	list<character*> characters;
	list<character*>::iterator it;


This is a snippet from a program that I wrote a while back. 'character' is a class, 'it' is basically a pointer that pages through the list 'characters' to look at specific ones.
closed account (zb0S216C)
menu_items.erase( menu_items.begin( ) + i );

Wazzak
Using advance would be slightly more general then operator+. However, a better approach would be to use an iterator to traverse the collection rather than an int. That way, you'll already have the iterator handy. One word of caution, though: erasing an element from a vector invalidates iterators--you'd have to reassign the return value from the erase call to the iterator.

Untested example:
1
2
3
4
5
6
vector< int > v;
for( vector< int >::iterator i = v.begin(); i != v.end(); ++i ) {
    /*if( something )*/ {.
        i = v.erase( i );
    }
}


* This example is flawed, please read on.
Last edited on
@moorecm: Explain more about how it invalidates. If I were to, as you exampled, v.erase(i); would I be able to use the iterator still, assuming that I reset it to i = v.begin();?
Vectors guarantee contiguous storage for elements. When you remove one, the elements beyond it must be shifted to meet the guarantee. That means an iterater "pointing to" an element may no longer point to the right element. It becomes invalid. The erase method returns an iterator to the next valid element after the operation. It's a good thing that you asked because that also means that my example is flawed. The element after the one that was erased will now be skipped over because of the loops ++i. Here's a better example:

1
2
3
4
5
6
7
8
9
vector< int > v;
vector< int >::iterator i = v.begin();
while( i != v.end() ) {
    if( /*something*/ ) {.
        i = v.erase( i );
    } else {
        ++i;
    }
}
Last edited on
So if I understand you correctly, any iterators that are not corrected will be invalid, but if you're simply using an iterator to page through the vector repeatedly, then the erase won't have any effect on it, assuming that you don't skip the next iteration by incrementing during an erase.

Or, in other words,
v.erase(iter);
causes v(iter-1), when it gets the command ++iter, to point to v(iter+1), instead of v(iter), which no longer exists, and the compiler automatically adjusts the value of iter to be the pointer of v(iter+1).
So if I understand you correctly, any iterators that are not corrected will be invalid


This is correct. You cannot make any assumptions about which element, if any at all, an iterator will refer to after it has been invalidated. When traversing a vector, you must reset the iterator to the return of the erase method to continue traversal.
Topic archived. No new replies allowed.