<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ESB Homepage &#187; C++</title>
	<atom:link href="http://www.ericscottbarr.com/blog/category/cpp/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ericscottbarr.com/blog</link>
	<description>Collecting and discussing my thoughts and ideas</description>
	<lastBuildDate>Tue, 19 Jan 2010 10:57:26 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>How to erase() From a Standard Container (std::map, std::list) in a Loop</title>
		<link>http://www.ericscottbarr.com/blog/2009/10/20/how-to-erase-from-a-stdmap-in-a-loop/</link>
		<comments>http://www.ericscottbarr.com/blog/2009/10/20/how-to-erase-from-a-stdmap-in-a-loop/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 09:18:54 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://www.ericscottbarr.com/blog/?p=3</guid>
		<description><![CDATA[I recently came across a bit of code that was essentially a &#8216;find and erase&#8217; process on a std::map that essentially boiled down to the following:

typedef std::map&#60;int, int&#62; MyMap;

MyMap my_map;
MyMap::iterator end = my_map.end();

for (MyMap::iterator i = my_map.begin(); i != end; ++i) {
	// Search for some value within the loop.
	if (i-&#62;second = 5){
		i = my_map.erase(i);
	}
}

On Visual [...]]]></description>
			<content:encoded><![CDATA[<p>I recently came across a bit of code that was essentially a &#8216;find and erase&#8217; process on a std::map that essentially boiled down to the following:</p>
<pre class="brush: cpp;">
typedef std::map&lt;int, int&gt; MyMap;

MyMap my_map;
MyMap::iterator end = my_map.end();

for (MyMap::iterator i = my_map.begin(); i != end; ++i) {
	// Search for some value within the loop.
	if (i-&gt;second = 5){
		i = my_map.erase(i);
	}
}
</pre>
<p>On Visual Studio 2008 this will even compile. However, for those of you who may be moving code over to GCC you may find there&#8217;s an issue that results in errors similar to the following:</p>
<pre class="brush: plain;">
error: no match for 'operator=' in (...) // Followed by a lot of stl template errors.
</pre>
<p>The answer is simple: erase doesn&#8217;t return an iterator&#8230; it returns void! A simple adjustment to the algorithm and everything compiles nicely on all compilers:</p>
<pre class="brush: cpp;">
typedef std::map&lt;int, int&gt; MyMap;

MyMap my_map;
MyMap::iterator end = my_map.end();

for (MyMap::iterator i = my_map.begin(); i != end; ++i) {
	// Search for some value within the loop.
	if (i-&gt;second = 5){
		my_map.erase(i++); // Increment the iterator
	}
}
</pre>
<p>Here a post increment is used (to avoid incrementing first and erasing the item after the desired one!) to ensure the loop continues on successfully.</p>
<p><strong>UPDATE</strong></p>
<p>Sometime after writing this I was working on testing code where a single element was being added to a standard container and then removed through a method similar to the above. Doing so generates an error like the ones below:</p>
<blockquote><p><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">map iterator not incrementable</span></p>
<p><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">OR</span></p>
<p><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">list iterator not incrementor</span></p></blockquote>
<p>The reason for the error is that calling erase(i++) on the last element in a container sets i to the end() value. When the next iteration of the for loop comes around the iterator attempts to move one past the end and that&#8217;s when the assertion is hit. This can be fixed by revising the above solution and moving the iterator incrementation from the for header to it&#8217;s body. With that change here is the final solution:</p>
<pre style="font: normal normal normal 12px/18px Consolas, Monaco, 'Courier New', Courier, monospace;">
<pre>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 992px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
<pre class="brush: cpp;">&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 992px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;typedef std::map&lt;int, int&gt; MyMap;&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 992px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;MyMap my_map;&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 992px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;MyMap::iterator end = my_map.end();&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 992px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;for (MyMap::iterator i = my_map.begin(); i != end;) {&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 992px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;// Search for some value within the loop.&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 992px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;if (i-&gt;second = 5){&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 992px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;my_map.erase(i++); // Increment the iterator&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 992px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;} else {&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 992px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;++i;&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 992px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;}&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 992px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;}&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 992px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;</pre>
</div>
<pre class="brush: cpp;">
typedef std::map&lt;int, int&gt; MyMap;

MyMap my_map;
MyMap::iterator end = my_map.end();

for (MyMap::iterator i = my_map.begin(); i != end;) {
	// Search for some value within the loop.
	if (i-&gt;second = 5){
		my_map.erase(i++); // Increment the iterator
	} else {
		++i;
	}
}
</pre>
</pre>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ericscottbarr.com/blog/2009/10/20/how-to-erase-from-a-stdmap-in-a-loop/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
