Boost C++ Libraries: Ticket #10514: Cannot copy const sub_range to non-const https://svn.boost.org/trac10/ticket/10514 <p> The following code does not compile with Visual Studio 2013 using Boost 1.56.0: </p> <div class="wiki-code"><div class="code"><pre><span class="k">typedef</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">vec_t</span><span class="p">;</span> <span class="k">typedef</span> <span class="n">boost</span><span class="o">::</span><span class="n">sub_range</span><span class="o">&lt;</span><span class="n">vec_t</span><span class="o">&gt;</span> <span class="n">range_t</span><span class="p">;</span> <span class="n">vec_t</span> <span class="nf">vec</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> <span class="n">range_t</span> <span class="nf">r</span><span class="p">(</span><span class="n">vec</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">vec</span><span class="p">.</span><span class="n">end</span><span class="p">());</span> <span class="k">const</span> <span class="n">range_t</span> <span class="o">&amp;</span> <span class="n">r_ref</span> <span class="o">=</span> <span class="n">r</span><span class="p">;</span> <span class="n">range_t</span> <span class="n">v</span> <span class="o">=</span> <span class="n">r_ref</span><span class="p">;</span> </pre></div></div><p> The following error results: </p> <pre class="wiki">boost/range/iterator_range_core.hpp(69) : error C2440: 'static_cast' : cannot convert from 'std::_Vector_const_iterator&lt;std::_Vector_val&lt;std::_Simple_types&lt;int&gt;&gt;&gt;' to 'std::_Vector_iterator&lt;std::_Vector_val&lt;std::_Simple_types&lt;int&gt;&gt;&gt;' No constructor could take the source type, or constructor overload resolution was ambiguous c:\build\ng-10.5-x64\API\inc\boost/range/sub_range.hpp(184) : see reference to function template instantiation 'IteratorT boost::iterator_range_detail::iterator_range_impl&lt;IteratorT&gt;::adl_begin&lt;const boost::range_detail::sub_range_base&lt;ForwardRange,boost::random_access_traversal_tag&gt;&gt;(const boost::range_detail::sub_range_base&lt;ForwardRange,boost::random_access_traversal_tag&gt; &amp;)' being compiled with [ IteratorT=std::_Vector_iterator&lt;std::_Vector_val&lt;std::_Simple_types&lt;int&gt;&gt;&gt; , ForwardRange=vec_t ] c:\build\ng-10.5-x64\API\inc\boost/range/sub_range.hpp(187) : see reference to function template instantiation 'IteratorT boost::iterator_range_detail::iterator_range_impl&lt;IteratorT&gt;::adl_begin&lt;const boost::range_detail::sub_range_base&lt;ForwardRange,boost::random_access_traversal_tag&gt;&gt;(const boost::range_detail::sub_range_base&lt;ForwardRange,boost::random_access_traversal_tag&gt; &amp;)' being compiled with [ IteratorT=std::_Vector_iterator&lt;std::_Vector_val&lt;std::_Simple_types&lt;int&gt;&gt;&gt; , ForwardRange=vec_t ] c:\build\ng-10.5-x64\API\inc\boost/range/sub_range.hpp(184) : while compiling class template member function 'boost::sub_range&lt;vec_t&gt;::sub_range(const boost::sub_range&lt;vec_t&gt; &amp;)' sub_range_test.cpp(11) : see reference to function template instantiation 'boost::sub_range&lt;vec_t&gt;::sub_range(const boost::sub_range&lt;vec_t&gt; &amp;)' being compiled sub_range_test.cpp(9) : see reference to class template instantiation 'boost::sub_range&lt;vec_t&gt;' being compiled boost/range/iterator_range_core.hpp(75) : error C2440: 'static_cast' : cannot convert from 'std::_Vector_const_iterator&lt;std::_Vector_val&lt;std::_Simple_types&lt;int&gt;&gt;&gt;' to 'std::_Vector_iterator&lt;std::_Vector_val&lt;std::_Simple_types&lt;int&gt;&gt;&gt;' No constructor could take the source type, or constructor overload resolution was ambiguous c:\build\ng-10.5-x64\API\inc\boost/range/sub_range.hpp(186) : see reference to function template instantiation 'IteratorT boost::iterator_range_detail::iterator_range_impl&lt;IteratorT&gt;::adl_end&lt;const boost::range_detail::sub_range_base&lt;ForwardRange,boost::random_access_traversal_tag&gt;&gt;(const boost::range_detail::sub_range_base&lt;ForwardRange,boost::random_access_traversal_tag&gt; &amp;)' being compiled with [ IteratorT=std::_Vector_iterator&lt;std::_Vector_val&lt;std::_Simple_types&lt;int&gt;&gt;&gt; , ForwardRange=vec_t ] c:\build\ng-10.5-x64\API\inc\boost/range/sub_range.hpp(187) : see reference to function template instantiation 'IteratorT boost::iterator_range_detail::iterator_range_impl&lt;IteratorT&gt;::adl_end&lt;const boost::range_detail::sub_range_base&lt;ForwardRange,boost::random_access_traversal_tag&gt;&gt;(const boost::range_detail::sub_range_base&lt;ForwardRange,boost::random_access_traversal_tag&gt; &amp;)' being compiled with [ IteratorT=std::_Vector_iterator&lt;std::_Vector_val&lt;std::_Simple_types&lt;int&gt;&gt;&gt; , ForwardRange=vec_t ] </pre><p> So it looks as though having a <code>const</code> <code>sub_range</code> implies that it uses <code>const_iterator</code>s, which doesn't seem appropriate. </p> <p> Code of this nature compiled using Boost 1.55.0. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/10514 Trac 1.4.3 Braden McDaniel <braden@…> Thu, 18 Sep 2014 04:26:12 GMT attachment set https://svn.boost.org/trac10/ticket/10514 https://svn.boost.org/trac10/ticket/10514 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">sub_range_test.cpp</span> </li> </ul> <p> Test case </p> Ticket Neil Groves Mon, 02 Feb 2015 01:18:55 GMT status changed; resolution set https://svn.boost.org/trac10/ticket/10514#comment:1 https://svn.boost.org/trac10/ticket/10514#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">invalid</span> </li> </ul> <p> The propagation of const-ness is the rationale for having sub_range in addition to iterator_range. Please see: <a href="http://www.boost.org/doc/libs/1_57_0/libs/range/doc/html/range/reference/utilities/sub_range.html">http://www.boost.org/doc/libs/1_57_0/libs/range/doc/html/range/reference/utilities/sub_range.html</a> </p> <p> If you do not wish to propagate const-ness please use iterator_range instead. </p> Ticket Braden McDaniel <braden@…> Mon, 02 Feb 2015 02:27:40 GMT status changed; resolution deleted https://svn.boost.org/trac10/ticket/10514#comment:2 https://svn.boost.org/trac10/ticket/10514#comment:2 <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">invalid</span> </li> </ul> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/10514#comment:1" title="Comment 1">neilgroves</a>: </p> <blockquote class="citation"> <p> The propagation of const-ness is the rationale for having sub_range in addition to iterator_range. Please see: <a href="http://www.boost.org/doc/libs/1_57_0/libs/range/doc/html/range/reference/utilities/sub_range.html">http://www.boost.org/doc/libs/1_57_0/libs/range/doc/html/range/reference/utilities/sub_range.html</a> </p> <p> If you do not wish to propagate const-ness please use iterator_range instead. </p> </blockquote> <p> It appears to me that <code>const</code> is being propagating incorrectly in this case. At the very least, <code>const</code> is being propagated in a way that is inconsistent with how it is normally propagated with the standard containers. Consider the analogous example using just <code>std::vector</code>: </p> <div class="wiki-code"><div class="code"><pre><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">v</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="o">&amp;</span> <span class="n">v_ref</span> <span class="o">=</span> <span class="n">v</span><span class="p">;</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">u</span> <span class="o">=</span> <span class="n">v_ref</span><span class="p">;</span> </pre></div></div><p> This compiles just fine because there is no problem copying a <code>const int</code> to an <code>int</code>. To the point: it doesn't matter that <code>v_ref</code> uses <code>const_iterator</code>s. </p> <p> (So, I may have framed the problem incorrectly in my initial description. The problem isn't that <code>const_iterator</code>s are being used at all; the problem is that <code>sub_range</code> seems to insist that the lhs use <code>const_iterator</code>s just because the rhs does.) </p> Ticket Neil Groves Mon, 02 Feb 2015 09:05:54 GMT status changed https://svn.boost.org/trac10/ticket/10514#comment:3 https://svn.boost.org/trac10/ticket/10514#comment:3 <ul> <li><strong>status</strong> <span class="trac-field-old">reopened</span> → <span class="trac-field-new">new</span> </li> </ul> <p> I didn't comprehend initially that the snippet of code posted compiled with 1.55. I apologise for not understanding this despite you correctly putting the severity as regression. </p> <p> Upon closer inspection this does appear like it ought to compile but not for the reasons you described. It is indeed intended for a const sub_range to return const_iterator. The strange issue is that const_iterator is not converting to iterator. This might be related to a problem in Boost 1.57 where Boost.Range had some specialisations of Boost.Iterator and Boost.Iterator had the namespace changed for the class specialised within Boost.Range. If it is related to this, then the "develop" and "master" branch of Boost.Range already contain a fix. </p> <p> I have to do my day job for a bit, but I'll get back to looking at this as soon as I can. I don't have any Microsoft C++ compilers other than the free ones anymore. Hopefully this will show up on Clang or GCC when I try them. </p> <p> Depending on the urgency of this defect, you may wish to pull the branches to see if they solve the problem. I'm aiming to look at this again later tonight. </p> Ticket Neil Groves Mon, 02 Feb 2015 20:28:45 GMT <link>https://svn.boost.org/trac10/ticket/10514#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/10514#comment:4</guid> <description> <p> Okay, I added a unit test for the scenario provided to the develop branch and it compiles cleanly. I believe that the problem has already been fixed. I think it is related to the missed template specialisation due to a mismatch between my specialisation and the changed namespace in Boost.Iterator. </p> <p> I will not close the defect just yet. I'll watch this test cycle, and look closely at the MSVC regression tests. Hopefully these will pass, and I can just do a simple merge for release 1.58 to add this test case to ensure this doesn't happen again. </p> <p> Sorry for the hassle. </p> </description> <category>Ticket</category> </item> </channel> </rss>