[iterators][range] size compile failure in 1.35

I'm moving from 1.34.1 to 1.35.0 The following compiles in 1.34.1 and fails in 1.35.0 on MSVC 8. Any thoughts on how to correct this? #include <vector> #include <boost/bind.hpp> #include <boost/iterator/filter_iterator.hpp> #include <boost/range/iterator_range.hpp> template<class Predicate, class Range> boost::iterator_range<boost::filter_iterator<Predicate, typename Range::iterator> > filteredRange(Range& range, Predicate p) { return boost::make_iterator_range( boost::make_filter_iterator<Predicate>(p, range.begin(), range.end()), boost::make_filter_iterator<Predicate>(p, range. end(), range.end())); } bool filt(int ) { return true; } int main() { std::vector<int> c; filteredRange(c, boost::bind(&filt, _1)).size(); return 0; } And the errors are: 1>IteratorAndRangeSizeTest.cpp 1>f:\gene_codes\external_libraries\boost_1_35_0\boost\iterator\iterator_adaptor.hpp(225) : error C2027: use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>' 1> with 1> [ 1> x=false 1> ] 1> f:\gene_codes\external_libraries\boost_1_35_0\boost\iterator\iterator_adaptor.hpp(348) : see reference to function template instantiation 'void boost::detail::iterator_adaptor_assert_traversal<boost::bidirectional_traversal_tag,boost::random_access_traversal_tag>(void)' being compiled 1> f:\gene_codes\external_libraries\boost_1_35_0\boost\iterator\iterator_facade.hpp(554) : see reference to function template instantiation '__w64 int boost::iterator_adaptor<Derived,Base,Value,Traversal>::distance_to<boost::filter_iterator<Predicate,Iterator>,Iterator,boost::use_default,boost::bidirectional_traversal_tag,boost::use_default,boost::use_default>(const boost::iterator_adaptor<Derived,Base,Value,Traversal> &) const' being compiled 1> with 1> [ 1> Derived=boost::filter_iterator<boost::_bi::bind_t<bool,bool (__cdecl *)(int),boost::_bi::list1<boost::arg<1>>>,std::_Vector_iterator<int,std::allocator<int>>>, 1> Base=std::_Vector_iterator<int,std::allocator<int>>, 1> Value=boost::use_default, 1> Traversal=boost::bidirectional_traversal_tag, 1> Predicate=boost::_bi::bind_t<bool,bool (__cdecl *)(int),boost::_bi::list1<boost::arg<1>>>, 1> Iterator=std::_Vector_iterator<int,std::allocator<int>> 1> ] 1> f:\gene_codes\external_libraries\boost_1_35_0\boost\iterator\iterator_facade.hpp(852) : see reference to function template instantiation '__w64 int boost::iterator_core_access::distance_from<Derived1,Derived2>(const Facade1 &,const Facade2 &,boost::mpl::true_)' being compiled 1> with 1> [ 1> Derived1=boost::filter_iterator<boost::_bi::bind_t<bool,bool (__cdecl *)(int),boost::_bi::list1<boost::arg<1>>>,std::_Vector_iterator<int,std::allocator<int>>>, 1> Derived2=boost::filter_iterator<boost::_bi::bind_t<bool,bool (__cdecl *)(int),boost::_bi::list1<boost::arg<1>>>,std::_Vector_iterator<int,std::allocator<int>>>, 1> Facade1=boost::filter_iterator<boost::_bi::bind_t<bool,bool (__cdecl *)(int),boost::_bi::list1<boost::arg<1>>>,std::_Vector_iterator<int,std::allocator<int>>>, 1> Facade2=boost::filter_iterator<boost::_bi::bind_t<bool,bool (__cdecl *)(int),boost::_bi::list1<boost::arg<1>>>,std::_Vector_iterator<int,std::allocator<int>>> 1> ] 1> f:\gene_codes\external_libraries\boost_1_35_0\boost\range\iterator_range.hpp(278) : see reference to function template instantiation '__w64 int boost::operator -<Derived,int,boost::bidirectional_traversal_tag,int&,__w64 int,Derived,int,boost::bidirectional_traversal_tag,int&,__w64 int>(const boost::iterator_facade<Derived,Value,CategoryOrTraversal,Reference,Difference> &,const boost::iterator_facade<Derived,Value,CategoryOrTraversal,Reference,Difference> &)' being compiled 1> with 1> [ 1> Derived=boost::filter_iterator<boost::_bi::bind_t<bool,bool (__cdecl *)(int),boost::_bi::list1<boost::arg<1>>>,std::_Vector_iterator<int,std::allocator<int>>>, 1> Value=int, 1> CategoryOrTraversal=boost::bidirectional_traversal_tag, 1> Reference=int &, 1> Difference=__w64 int 1> ] 1> f:\gene_codes\external_libraries\boost_1_35_0\boost\range\iterator_range.hpp(276) : while compiling class template member function '__w64 int boost::iterator_range<IteratorT>::size(void) const' 1> with 1> [ 1> IteratorT=boost::filter_iterator<boost::_bi::bind_t<bool,bool (__cdecl *)(int),boost::_bi::list1<boost::arg<1>>>,std::_Vector_iterator<int,std::allocator<int>>> 1> ] 1> f:\dev\iteratorandrangesizetest\iteratorandrangesizetest.cpp(24) : see reference to class template instantiation 'boost::iterator_range<IteratorT>' being compiled 1> with 1> [ 1> IteratorT=boost::filter_iterator<boost::_bi::bind_t<bool,bool (__cdecl *)(int),boost::_bi::list1<boost::arg<1>>>,std::_Vector_iterator<int,std::allocator<int>>> 1> ] Thanks, Jeff

on Fri Jun 06 2008, Jeff Flinn <TriumphSprint2000-AT-hotmail.com> wrote:
I'm moving from 1.34.1 to 1.35.0
The following compiles in 1.34.1 and fails in 1.35.0 on MSVC 8. Any thoughts on how to correct this?
Jeff, in 1.35 I'm pretty sure that iterator_range<T>::size() only works when T is a random access iterator, and filtered iterators are by necessity bidirectional. I suggest you use std::distance(r.begin(), r.end()) if you're willing to pay for O(N) execution. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

David Abrahams wrote:
on Fri Jun 06 2008, Jeff Flinn <TriumphSprint2000-AT-hotmail.com> wrote:
I'm moving from 1.34.1 to 1.35.0
The following compiles in 1.34.1 and fails in 1.35.0 on MSVC 8. Any thoughts on how to correct this?
Jeff,
in 1.35 I'm pretty sure that iterator_range<T>::size() only works when T is a random access iterator, and filtered iterators are by necessity bidirectional. I suggest you use
std::distance(r.begin(), r.end())
if you're willing to pay for O(N) execution.
Hmm, it looks like that's what iterator_range<T>::size() did in 1.34.1 while 1.35 returns m_Begin - m_End. Any idea why this was done? Thanks, Jeff

On Fri, Jun 6, 2008 at 7:28 PM, Jeff Flinn <TriumphSprint2000@hotmail.com> wrote:
David Abrahams wrote:
on Fri Jun 06 2008, Jeff Flinn <TriumphSprint2000-AT-hotmail.com> wrote:
I'm moving from 1.34.1 to 1.35.0
The following compiles in 1.34.1 and fails in 1.35.0 on MSVC 8. Any thoughts on how to correct this?
Jeff,
in 1.35 I'm pretty sure that iterator_range<T>::size() only works when T is a random access iterator, and filtered iterators are by necessity bidirectional. I suggest you use
std::distance(r.begin(), r.end())
if you're willing to pay for O(N) execution.
Hmm, it looks like that's what iterator_range<T>::size() did in 1.34.1 while 1.35 returns m_Begin - m_End. Any idea why this was done?
To guarantee that it will only compiles if it can be implemented efficiently (i.e. only for random access iterators). Looking at the docs, it seems that boost range also provides a range based distance that will work for all iterators but doesn't guarantee O(1) complexity. -- gpd

Jeff Flinn skrev:
David Abrahams wrote:
in 1.35 I'm pretty sure that iterator_range<T>::size() only works when T is a random access iterator, and filtered iterators are by necessity bidirectional. I suggest you use
std::distance(r.begin(), r.end())
if you're willing to pay for O(N) execution.
Hmm, it looks like that's what iterator_range<T>::size() did in 1.34.1 while 1.35 returns m_Begin - m_End. Any idea why this was done?
boost::distance(r) could also work. I did it as part of the general clean-up of the range lib. size() is expected to be O(1) by users, distance() is not. -Thorsten
participants (4)
-
David Abrahams
-
Giovanni Piero Deretta
-
Jeff Flinn
-
Thorsten Ottosen