Boost C++ Libraries: Ticket #3659: warning when using boost::counting_iterator<int> and std::vector<int> on MSVC https://svn.boost.org/trac10/ticket/3659 <p> This code causes the warnings: </p> <p> #include &lt;boost/iterator/counting_iterator.hpp&gt; #include &lt;vector&gt; </p> <p> int main() </p> <blockquote> <p> { boost::counting_iterator&lt;int&gt; </p> <blockquote> <p> begin, end; </p> </blockquote> </blockquote> <blockquote> <p> std::vector&lt;int&gt; v(begin, end); </p> </blockquote> <blockquote> <p> return 0; } </p> </blockquote> <p> warning C4244: '+=' : conversion from '<span class="underline">int64' to 'unsigned int', possible loss of data 1&gt; e:\program files\microsoft visual studio 8\vc\include\xutility(1702) : see reference to function template instantiation 'void std::_Distance2&lt;_InIt,_Diff&gt;(_RanIt,_RanIt,_Diff &amp;,std::random_access_iterator_tag)' being compiled 1&gt; with 1&gt; [ 1&gt; _InIt=boost::counting_iterator&lt;int&gt;, 1&gt; _Diff=unsigned int, 1&gt; _RanIt=boost::counting_iterator&lt;int&gt; 1&gt; ] </span></p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/3659 Trac 1.4.3 Steven Watanabe Wed, 09 Jun 2010 03:56:38 GMT status changed; resolution set https://svn.boost.org/trac10/ticket/3659#comment:1 https://svn.boost.org/trac10/ticket/3659#comment:1 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">wontfix</span> </li> </ul> <p> I don't think this is fixable. The difference type of counting_iterator is deliberately set to intmax_t, so that any difference can be represented. You can explicitly set the difference type to something else, if you really want to. </p> Ticket Sergey Mitsyn <svm at jinr.ru> Sat, 04 Jun 2011 11:28:23 GMT <link>https://svn.boost.org/trac10/ticket/3659#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3659#comment:2</guid> <description> <p> The warning still doesn't go when the difference type is explicitly specified instead of the default: </p> <pre class="wiki">#include &lt;boost/iterator/counting_iterator.hpp&gt; int main() { boost::counting_iterator&lt;int, boost::use_default, int&gt; a(0), b(10); a+=(b-a); return 0; } </pre><p> the compiler complains with the following: </p> <pre class="wiki">boost_1_43_0\boost\iterator\counting_iterator.hpp(139) : warning C4244: 'return' : conversion from '__int64' to 'int', possible loss of data </pre><p> IMHO looks like the C-style cast to <code> numeric_distance </code> forces the difference to be intmax_t, and implicit conversion to return type <code> Difference </code> invokes the warning. </p> <p> Maybe it's OK to assume that if a user specifies the difference type explicitly, he/she knows what he/she is doing and use static_cast to <code> Difference </code>? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Sat, 04 Jun 2011 11:29:50 GMT</pubDate> <title>status changed; resolution deleted https://svn.boost.org/trac10/ticket/3659#comment:3 https://svn.boost.org/trac10/ticket/3659#comment:3 <ul> <li><strong>status</strong> <span class="trac-field-old">closed</span> → <span class="trac-field-new">reopened</span> </li> <li><strong>resolution</strong> <span class="trac-field-deleted">wontfix</span> </li> </ul> Ticket Dave Abrahams Sat, 04 Jun 2011 22:38:27 GMT <link>https://svn.boost.org/trac10/ticket/3659#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3659#comment:4</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/3659#comment:2" title="Comment 2">Sergey Mitsyn &lt;svm at jinr.ru&gt;</a>: </p> <blockquote class="citation"> <p> IMHO looks like the C-style cast to <code> numeric_distance </code> forces the difference to be intmax_t, and implicit conversion to return type <code> Difference </code> invokes the warning. </p> </blockquote> <p> There's no C-style cast. That's calling numeric_distance from boost/detail/numeric_traits.hpp. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Dave Abrahams</dc:creator> <pubDate>Sat, 04 Jun 2011 22:42:36 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/3659#comment:5 https://svn.boost.org/trac10/ticket/3659#comment:5 <ul> <li><strong>status</strong> <span class="trac-field-old">reopened</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">invalid</span> </li> </ul> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/3659#comment:2" title="Comment 2">Sergey Mitsyn &lt;svm at jinr.ru&gt;</a>: </p> <blockquote class="citation"> <p> The warning still doesn't go when the difference type is explicitly specified instead of the default: </p> <p> Maybe it's OK to assume that if a user specifies the difference type explicitly, he/she knows what he/she is doing and use static_cast to <code> Difference </code>? </p> </blockquote> <p> Maybe the warning is a good thing. I object most strongly to introducing casts to suppress warnings, especially in libraries: casts hide bugs. If you can find a way to make the warning go away without casting, I'll accept a patch. Otherwise, I think the compiler may be telling you that you're doing something you shouldn't do, and this is not a bug in the library. </p> Ticket Sergey Mitsyn <svm at jinr.ru> Sun, 05 Jun 2011 08:06:45 GMT <link>https://svn.boost.org/trac10/ticket/3659#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3659#comment:6</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/3659#comment:5" title="Comment 5">dave</a>: </p> <blockquote class="citation"> <p> There's no C-style cast. That's calling numeric_distance from boost/detail/numeric_traits.hpp. </p> </blockquote> <p> Yes, sorry, I've missed that. </p> <blockquote class="citation"> <p> Otherwise, I think the compiler may be telling you that you're doing something you shouldn't do, and this is not a bug in the library. </p> </blockquote> <p> IMHO taking a difference between two iterators is not a thing everybody shouldn't do, which is the case if <code> Difference </code> type is specified as <code>int</code>. And adding a difference between two iterators to an iterator of the same type is not a thing everybody shouldn't do either, which is the case with default <code> Difference </code> type. </p> <hr /> <p> Ok, i've investigated the problem a little more. The actual problem i'm faced is warning in the following code: </p> <pre class="wiki"> typedef boost::counting_iterator&lt;int, boost::use_default&gt; iterator_type; //typedef boost::counting_iterator&lt;int, boost::bidirectional_traversal_tag&gt; iterator_type; iterator_type a(0), b(10); std::vector&lt;int&gt; v(10, 0); std::copy( a,b,v.begin() ); </pre><p> The actual warning may be reproduced by this code (inside std::copy implementation): </p> <pre class="wiki"> std::vector&lt;int&gt;::iterator it = v.begin(); it += b-a; </pre><p> The <code>std::allocator&lt;T&gt;::difference_type</code> that is used by <code>std::vector</code> is defined as <code>ptrdiff_t</code>, which is <code>int</code> for 32-bit target. Thus, <code>std::vector::iterator::operator+=</code> has 32-bit integer as an argument. </p> <p> On the other hand, <code>boost::integer_traits</code> defines <code>difference_type</code> to be 64-bit <code>intmax_t</code> if <code>Integer</code> and <code>ptrdiff_t</code> are the same size, which is the case. Thus, the return type of <code>operator-</code> for <code>boost::counting_iterator</code> is 64-bit integer. Passing it to operator+= causes the warning. </p> <p> What I'm thinking about now is the fact that Dinkumware used 32-bit integer for 32-bit machine architecture instead of 64-bit, thus ignoring the requirement to represent any difference, as Steven stated above. Maybe Boost could also switch to using 32-bit ptrdiff_t with the same reason as Dinkumware does, at least for MSVC? </p> <hr /> <p> Also the interesting fact is that for <code>boost::counting_iterator&lt;short&gt;</code> no warning is shown, because it's <code>difference_type</code> is <code>ptrdiff_t</code>. But such workaround is unacceptable when there's a need in values bigger than 32767 :(. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Dave Abrahams</dc:creator> <pubDate>Sun, 05 Jun 2011 12:29:30 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3659#comment:7 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3659#comment:7</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/3659#comment:6" title="Comment 6">Sergey Mitsyn &lt;svm at jinr.ru&gt;</a>: </p> <blockquote class="citation"> <p> What I'm thinking about now is the fact that Dinkumware used 32-bit integer for 32-bit machine architecture instead of 64-bit, thus ignoring the requirement to represent any difference, as Steven stated above. Maybe Boost could also switch to using 32-bit ptrdiff_t with the same reason as Dinkumware does, at least for MSVC? </p> </blockquote> <p> <code>ptrdiff_t</code> is supplied by the standard library (i.e. Dinkumware) and not defined by Boost. We use whatever definition we get from the library. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Sergey Mitsyn <svm at jinr.ru></dc:creator> <pubDate>Sun, 05 Jun 2011 13:58:20 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3659#comment:8 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3659#comment:8</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/3659#comment:7" title="Comment 7">dave</a>: </p> <blockquote class="citation"> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/3659#comment:6" title="Comment 6">Sergey Mitsyn &lt;svm at jinr.ru&gt;</a>: </p> <blockquote class="citation"> <p> What I'm thinking about now is the fact that Dinkumware used 32-bit integer for 32-bit machine architecture instead of 64-bit, thus ignoring the requirement to represent any difference, as Steven stated above. Maybe Boost could also switch to using 32-bit ptrdiff_t with the same reason as Dinkumware does, at least for MSVC? </p> </blockquote> <p> <code>ptrdiff_t</code> is supplied by the standard library (i.e. Dinkumware) and not defined by Boost. We use whatever definition we get from the library. </p> </blockquote> <p> Sorry, I meant switching from intmax_t to ptrdiff_t, not redefining ptrdiff_t. What I meant to say is that <code>boost::counting_iterator</code> should move away from 'no-overflow' strategy, at least for MSVC + x86 and x64, because it would be more consistent with the Dinkumware STL implementation. </p> <p> Anyway, looks like it would be much easier to reimplement counting iterator with overflow-able strategy, or implement 'int' wrapper which plays nice with {{{boost::counting_iterator}} rather than fixing this "bug" in Boost. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Sergey Mitsyn <svm at jinr.ru></dc:creator> <pubDate>Mon, 06 Jun 2011 06:37:07 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3659#comment:9 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3659#comment:9</guid> <description> <p> BTW, not every difference is representable even with current strategy. In this code, difference overflows without issuing any warning: </p> <pre class="wiki">typedef boost::counting_iterator&lt;boost::intmax_t&gt; iterator_type; iterator_type a(-0x7ffFfffFfffFfffF), b(0x7ffFfffFfffFfffF); std::cout &lt;&lt; *a &lt;&lt; '\t' &lt;&lt; *b &lt;&lt; std::endl; std::cout &lt;&lt; (b-a) &lt;&lt; std::endl; </pre><p> , the output is: </p> <pre class="wiki">-9223372036854775807 9223372036854775807 -2 </pre><p> Thus <code>boost::counting_iterator</code> cannot provide guarantee that <code>(b-a)</code> cannot overflow for any <code>Incrementable</code>. Plus, I believe that everybody would expect <code>(b-a)</code> to be equal to <code>(*b-*a)</code>. </p> <p> Please, switch to strategy with overflows. :) </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Sergey Mitsyn <svm at jinr.ru></dc:creator> <pubDate>Mon, 06 Jun 2011 07:09:04 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3659#comment:10 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3659#comment:10</guid> <description> <p> Hello again, </p> <p> I've found <a class="ext-link" href="http://lists.boost.org/Archives/boost/2008/03/134556.php"><span class="icon">​</span>http://lists.boost.org/Archives/boost/2008/03/134556.php</a>. Okay, now the reason to set difference_type to be intmax_t is perfectly clear to me. Also, I see that boost::counting_iterator&lt;intmax_t&gt; may trigger undefined behavior (as in the example I listed above). </p> <p> But still i would like to have an option for <code>boost::counting_iterator</code> (or another counting iterator that is not called exactly <code>boost::counting_iterator</code>) so it does not spam my console with compiler warnings. </p> <p> wbr, </p> </description> <category>Ticket</category> </item> </channel> </rss>