This question already has answers here:
How to call erase with a reverse iterator
(13 answers)
Closed 6 years ago.
Is something wrong with erasing with reverse iterator? When compiling the code fragment below, I receive 'no matching function' error when using 'rit' as argument for erase().
std::vector<MyRecord*>* BLV = GetVector;
for (std::vector<MyRecord*>::iterator it = BLV->begin(); it != BLV->end(); ++it)
BLV->erase(it);
for (std::vector<MyRecord*>::reverse_iterator rit = BLV->rbegin(); rit != BLV->rend(); ++rit)
BLV->erase(rit);
Indeed erase cannot be used directly with a reverse iterator; you'd essentially be removing the wrong element if it were allowed.
You need to convert rit to a forward iterator.
(rit + 1).base(); will give you the equivalent it. Note carefully the + 1.
Putting this together, write
BLV->erase((rit + 1).base());
in your reverse case.
Related
This question already has answers here:
Vector iterator erase giving me a runtime error?
(2 answers)
Replacing elements in vector using erase and insert
(3 answers)
Erasing from a std::vector while doing a for each?
(1 answer)
Closed 1 year ago.
So I have the following code, which is supposed to use an iterator to replace an element in a vector if it matches some given value "old".
using StringIter = std::vector<std::string>;
using StringVec = std::vector<std::string>;
void replace(StringVec ref, std::string old, std::string replacement)
{
for (StringIter::iterator it = ref.begin(); it != ref.end(); it++)
{
if (*it == old)
{
ref.erase(it);
ref.insert(it,replacement);
}
}
}
However, I get the following runtime error: "vector emplace iterator outside range". I've tried changing the order of erase and insert, and using insert(it-1,...) instead, but it doesn't work. Haven't found any solution to this exact problem after an hour or so of googling.
This question already has answers here:
iterate vector, remove certain items as I go
(3 answers)
Closed 6 years ago.
EDIT: This question refers specifically to std::lists - other similar questions on Stack Overflow refer to std::vectors
I'm using C++ and having trouble erasing an element from a std::list while iterating through it. I have a list of a custom class ('Objects' for the sake of this question), and my code looks like this:
for(auto i : Objects)
if(i.EraseFlag == true)
{
i = Objects.erase(i);
}
I'm getting the error: 'no matching function for call to std::list::erase(Object&)'
I believe this is the right way (as of C++11) to iterate through lists, erase an element and return an iterator that takes into account the erasure, but clearly I'm doing something wrong. Previously when using vectors I would use 'Objects.erase(Objects.begin() + i)' with i being an integer in a for loop, but given the access requirements of lists this won't work.
Help appreciated.
Thanks
Member function erase deals with iterators.
For such a task it would be correctly to use an ordinary for loop. For example
for ( auto it = Objects.begin(); it != Objects.end(); )
{
if ( it->EraseFlag ) it = Objects.erase( it );
else ++it;
}
Another approach is to use member function remove_if. For example
Objects.remove_if( []( const auto &value ) { return value.EraseFlag; } );
This question already has answers here:
Get a reverse iterator from a forward iterator without knowing the value type
(2 answers)
Closed 6 years ago.
I find a certain point in an std::map<int, X> via upper_bound and then from this point on I iterate backwards. My code looks something like:
MAP::reverse_iterator iter;
iter = _map.upper_bound(value); // Does not compile because upper_bound is not reverse_iterator
while(iter != rbegin()){
// logic
--iter;
}
I get a compile error because upper_bound() does not return a reverse_iterator.
What is the best approach to remedy this?
You need to convert your iterator to a reverse iterator:
auto iter = _map.upper_bound(value);
for (std::reverse_iterator<decltype(iter)> rit{iter}; rit != _map.rend(); ++rit) {
// Do whatever you want...
}
Note that you have to stop when reaching _map.rend(), not _map.rbegin(), and you need to increment the reverse iterator, not decrement it.
This question already has answers here:
How can I loop through a C++ map of maps?
(9 answers)
Closed 9 years ago.
So, I have an std::map<int, my_vector> and I want to go through each int and analyse the vector.
I haven't gotten to the part of analyzing the vector just yet, I'm still trying to figure out how to go through every single element on the map.
I know it is possible to have an iterator, but I didn't quite understood how it works, also, I don't know if there isn't a better way to do what I intend to do
You can simply iterate over the map. Each map element is an std::pair<key, mapped_type>, so first gives you the key, second the element.
std::map<int, my_vector> m = ....;
for (std::map<int, my_vector>::const_iterator it = m.begin(); it != m.end(); ++it)
{
//it-->first gives you the key (int)
//it->second gives you the mapped element (vector)
}
// C++11 range based for loop
for (const auto& elem : m)
{
//elem.first gives you the key (int)
//elem.second gives you the mapped element (vector)
}
Iterators are the perfect thing for this. Look around http://www.cplusplus.com/reference/map/map/begin/
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ Best way to check if an iterator is valid
Let's say I have a function which takes an iterator as its sole parameter as below.
void DoSomethingWithIterator(std::vector<int>::iterator iter)
{
// Check the pre-condition
assert( /* how to validate iter here? */ )
// Operate on iter afterwards
..
}
How do I know if iter is valid or not. By valid, I mean it points to a existing element inside the vector, e.g., from m_intVector.begin() to m_intVector.end().
In general, you can't do that. C++ types are designed to be maximally efficient and don't contain such additional information.
For example, vector's iterator is likely to be equivalent to a pointer to element (this is the case on my machine, using g++ 4.7.2).
> I mean it points to a existing element inside the vector, e.g., from m_intVector.begin() to m_intVector.end().
Sure. Just iterate through the contents of m_vector, and compare each iterator to iter.
for ( std::vector<int>::iterator it = m_intVector.begin (); it != m_intVector.end (); ++it )
if ( it == iter ) return true;
return false;
But I suspect that you won't want to pay for that kind of checking.