Opened 8 years ago
Last modified 8 years ago
#10514 new Bugs
Cannot copy const sub_range to non-const
Reported by: | Owned by: | Neil Groves | |
---|---|---|---|
Milestone: | To Be Determined | Component: | range |
Version: | Boost 1.56.0 | Severity: | Regression |
Keywords: | Cc: |
Description
The following code does not compile with Visual Studio 2013 using Boost 1.56.0:
typedef std::vector<int> vec_t; typedef boost::sub_range<vec_t> range_t; vec_t vec(10); range_t r(vec.begin(), vec.end()); const range_t & r_ref = r; range_t v = r_ref;
The following error results:
boost/range/iterator_range_core.hpp(69) : error C2440: 'static_cast' : cannot convert from 'std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<int>>>' to 'std::_Vector_iterator<std::_Vector_val<std::_Simple_types<int>>>' 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<IteratorT>::adl_begin<const boost::range_detail::sub_range_base<ForwardRange,boost::random_access_traversal_tag>>(const boost::range_detail::sub_range_base<ForwardRange,boost::random_access_traversal_tag> &)' being compiled with [ IteratorT=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<int>>> , 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<IteratorT>::adl_begin<const boost::range_detail::sub_range_base<ForwardRange,boost::random_access_traversal_tag>>(const boost::range_detail::sub_range_base<ForwardRange,boost::random_access_traversal_tag> &)' being compiled with [ IteratorT=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<int>>> , 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<vec_t>::sub_range(const boost::sub_range<vec_t> &)' sub_range_test.cpp(11) : see reference to function template instantiation 'boost::sub_range<vec_t>::sub_range(const boost::sub_range<vec_t> &)' being compiled sub_range_test.cpp(9) : see reference to class template instantiation 'boost::sub_range<vec_t>' being compiled boost/range/iterator_range_core.hpp(75) : error C2440: 'static_cast' : cannot convert from 'std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<int>>>' to 'std::_Vector_iterator<std::_Vector_val<std::_Simple_types<int>>>' 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<IteratorT>::adl_end<const boost::range_detail::sub_range_base<ForwardRange,boost::random_access_traversal_tag>>(const boost::range_detail::sub_range_base<ForwardRange,boost::random_access_traversal_tag> &)' being compiled with [ IteratorT=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<int>>> , 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<IteratorT>::adl_end<const boost::range_detail::sub_range_base<ForwardRange,boost::random_access_traversal_tag>>(const boost::range_detail::sub_range_base<ForwardRange,boost::random_access_traversal_tag> &)' being compiled with [ IteratorT=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<int>>> , ForwardRange=vec_t ]
So it looks as though having a const
sub_range
implies that it uses const_iterator
s, which doesn't seem appropriate.
Code of this nature compiled using Boost 1.55.0.
Attachments (1)
Change History (5)
by , 8 years ago
Attachment: | sub_range_test.cpp added |
---|
follow-up: 2 comment:1 by , 8 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
The propagation of const-ness is the rationale for having sub_range in addition to iterator_range. Please see: http://www.boost.org/doc/libs/1_57_0/libs/range/doc/html/range/reference/utilities/sub_range.html
If you do not wish to propagate const-ness please use iterator_range instead.
comment:2 by , 8 years ago
Resolution: | invalid |
---|---|
Status: | closed → reopened |
Replying to neilgroves:
The propagation of const-ness is the rationale for having sub_range in addition to iterator_range. Please see: http://www.boost.org/doc/libs/1_57_0/libs/range/doc/html/range/reference/utilities/sub_range.html
If you do not wish to propagate const-ness please use iterator_range instead.
It appears to me that const
is being propagating incorrectly in this case. At the very least, const
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 std::vector
:
std::vector<int> v(10); const std::vector<int> & v_ref = v; std::vector<int> u = v_ref;
This compiles just fine because there is no problem copying a const int
to an int
. To the point: it doesn't matter that v_ref
uses const_iterator
s.
(So, I may have framed the problem incorrectly in my initial description. The problem isn't that const_iterator
s are being used at all; the problem is that sub_range
seems to insist that the lhs use const_iterator
s just because the rhs does.)
comment:3 by , 8 years ago
Status: | reopened → new |
---|
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.
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.
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.
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.
comment:4 by , 8 years ago
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.
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.
Sorry for the hassle.
Test case