Compare commits

..

2 Commits

Author SHA1 Message Date
Andrey Semashev
c2b846c57d Added a test for filter_iterator converting constructor. 2025-04-02 00:13:07 +03:00
Andrey Semashev
1a7996ebd0 Fixed compilation of filter_iterator conversion constructor.
The constructor would attempt to access a private member of the source
iterator, which could have a different type and therefore have that
member inaccessible. Also, the storage forwarding constructor had incorrect
types used in the forwarding expressions, which caused further compilation
errors.

Fixes https://github.com/boostorg/iterator/issues/90.
2025-04-02 00:09:36 +03:00
2 changed files with 50 additions and 41 deletions

View File

@@ -46,6 +46,9 @@ class filter_iterator :
{
friend class iterator_core_access;
template< typename, typename >
friend class filter_iterator;
private:
using super_t = detail::filter_iterator_base_t< Predicate, Iterator >;
@@ -75,7 +78,7 @@ private:
template< typename Pred, typename Iter >
storage(Pred&& pred, Iter&& end) :
predicate_base(boost::empty_init_t{}, static_cast< Predicate&& >(pred)), m_end(static_cast< Iterator&& >(end))
predicate_base(boost::empty_init_t{}, static_cast< Pred&& >(pred)), m_end(static_cast< Iter&& >(end))
{
}

View File

@@ -36,13 +36,13 @@ int main()
// Concept checks
// Adapting old-style iterators
{
typedef boost::filter_iterator<one_or_four, boost::input_iterator_archetype<dummyT> > Iter;
using Iter = boost::filter_iterator<one_or_four, boost::input_iterator_archetype<dummyT> >;
boost::function_requires< boost::InputIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::SinglePassIteratorConcept<Iter> >();
}
{
typedef boost::filter_iterator<one_or_four, boost::input_output_iterator_archetype<dummyT> > Iter;
using Iter = boost::filter_iterator<one_or_four, boost::input_output_iterator_archetype<dummyT> >;
boost::function_requires< boost::InputIteratorConcept<Iter> >();
boost::function_requires< boost::OutputIteratorConcept<Iter, dummyT> >();
boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
@@ -50,39 +50,39 @@ int main()
boost::function_requires< boost_concepts::SinglePassIteratorConcept<Iter> >();
}
{
typedef boost::filter_iterator<one_or_four, boost::forward_iterator_archetype<dummyT> > Iter;
using Iter = boost::filter_iterator<one_or_four, boost::forward_iterator_archetype<dummyT> >;
boost::function_requires< boost::ForwardIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::ForwardTraversalConcept<Iter> >();
}
{
typedef boost::filter_iterator<one_or_four, boost::mutable_forward_iterator_archetype<dummyT> > Iter;
using Iter = boost::filter_iterator<one_or_four, boost::mutable_forward_iterator_archetype<dummyT> >;
boost::function_requires< boost::Mutable_ForwardIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::WritableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::ForwardTraversalConcept<Iter> >();
}
{
typedef boost::filter_iterator<one_or_four, boost::bidirectional_iterator_archetype<dummyT> > Iter;
using Iter = boost::filter_iterator<one_or_four, boost::bidirectional_iterator_archetype<dummyT> >;
boost::function_requires< boost::BidirectionalIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::BidirectionalTraversalConcept<Iter> >();
}
{
typedef boost::filter_iterator<one_or_four, boost::mutable_bidirectional_iterator_archetype<dummyT> > Iter;
using Iter = boost::filter_iterator<one_or_four, boost::mutable_bidirectional_iterator_archetype<dummyT> >;
boost::function_requires< boost::Mutable_BidirectionalIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::WritableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::BidirectionalTraversalConcept<Iter> >();
}
{
typedef boost::filter_iterator<one_or_four, boost::random_access_iterator_archetype<dummyT> > Iter;
using Iter = boost::filter_iterator<one_or_four, boost::random_access_iterator_archetype<dummyT> >;
boost::function_requires< boost::BidirectionalIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::BidirectionalTraversalConcept<Iter> >();
}
{
typedef boost::filter_iterator<one_or_four, boost::mutable_random_access_iterator_archetype<dummyT> > Iter;
using Iter = boost::filter_iterator<one_or_four, boost::mutable_random_access_iterator_archetype<dummyT> >;
boost::function_requires< boost::Mutable_BidirectionalIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::WritableIteratorConcept<Iter> >();
@@ -90,24 +90,24 @@ int main()
}
// Adapting new-style iterators
{
typedef boost::iterator_archetype<
using BaseIter = boost::iterator_archetype<
const dummyT
, boost::iterator_archetypes::readable_iterator_t
, boost::single_pass_traversal_tag
> BaseIter;
typedef boost::filter_iterator<one_or_four, BaseIter> Iter;
>;
using Iter = boost::filter_iterator<one_or_four, BaseIter>;
boost::function_requires< boost::InputIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::SinglePassIteratorConcept<Iter> >();
}
#if !BOOST_WORKAROUND(BOOST_MSVC, == 1200) // Causes Internal Error in linker.
{
typedef boost::iterator_archetype<
using BaseIter = boost::iterator_archetype<
dummyT
, boost::iterator_archetypes::readable_writable_iterator_t
, boost::single_pass_traversal_tag
> BaseIter;
typedef boost::filter_iterator<one_or_four, BaseIter> Iter;
>;
using Iter = boost::filter_iterator<one_or_four, BaseIter>;
boost::function_requires< boost::InputIteratorConcept<Iter> >();
boost::function_requires< boost::OutputIteratorConcept<Iter, dummyT> >();
@@ -117,12 +117,12 @@ int main()
}
#endif
{
typedef boost::iterator_archetype<
using BaseIter = boost::iterator_archetype<
const dummyT
, boost::iterator_archetypes::readable_iterator_t
, boost::forward_traversal_tag
> BaseIter;
typedef boost::filter_iterator<one_or_four, BaseIter> Iter;
>;
using Iter = boost::filter_iterator<one_or_four, BaseIter>;
boost::function_requires< boost::InputIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::ForwardTraversalConcept<Iter> >();
@@ -130,35 +130,35 @@ int main()
#if !BOOST_WORKAROUND(BOOST_MSVC, == 1200) // Causes Internal Error in linker.
{
typedef boost::iterator_archetype<
using BaseIter = boost::iterator_archetype<
dummyT
, boost::iterator_archetypes::readable_writable_iterator_t
, boost::forward_traversal_tag
> BaseIter;
typedef boost::filter_iterator<one_or_four, BaseIter> Iter;
>;
using Iter = boost::filter_iterator<one_or_four, BaseIter>;
boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::WritableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::ForwardTraversalConcept<Iter> >();
}
{
typedef boost::iterator_archetype<
using BaseIter = boost::iterator_archetype<
const dummyT
, boost::iterator_archetypes::readable_lvalue_iterator_t
, boost::forward_traversal_tag
> BaseIter;
typedef boost::filter_iterator<one_or_four, BaseIter> Iter;
>;
using Iter = boost::filter_iterator<one_or_four, BaseIter>;
boost::function_requires< boost::ForwardIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::LvalueIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::ForwardTraversalConcept<Iter> >();
}
{
typedef boost::iterator_archetype<
using BaseIter = boost::iterator_archetype<
dummyT
, boost::iterator_archetypes::writable_lvalue_iterator_t
, boost::forward_traversal_tag
> BaseIter;
typedef boost::filter_iterator<one_or_four, BaseIter> Iter;
>;
using Iter = boost::filter_iterator<one_or_four, BaseIter>;
boost::function_requires< boost::Mutable_ForwardIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::WritableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::LvalueIteratorConcept<Iter> >();
@@ -167,12 +167,12 @@ int main()
#endif
{
typedef boost::iterator_archetype<
using BaseIter = boost::iterator_archetype<
const dummyT
, boost::iterator_archetypes::readable_iterator_t
, boost::random_access_traversal_tag
> BaseIter;
typedef boost::filter_iterator<one_or_four, BaseIter> Iter;
>;
using Iter = boost::filter_iterator<one_or_four, BaseIter>;
boost::function_requires< boost::InputIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::BidirectionalTraversalConcept<Iter> >();
@@ -180,35 +180,35 @@ int main()
#if !BOOST_WORKAROUND(BOOST_MSVC, == 1200) // Causes Internal Error in linker.
{
typedef boost::iterator_archetype<
using BaseIter = boost::iterator_archetype<
dummyT
, boost::iterator_archetypes::readable_writable_iterator_t
, boost::random_access_traversal_tag
> BaseIter;
typedef boost::filter_iterator<one_or_four, BaseIter> Iter;
>;
using Iter = boost::filter_iterator<one_or_four, BaseIter>;
boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::WritableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::BidirectionalTraversalConcept<Iter> >();
}
{
typedef boost::iterator_archetype<
using BaseIter = boost::iterator_archetype<
const dummyT
, boost::iterator_archetypes::readable_lvalue_iterator_t
, boost::random_access_traversal_tag
> BaseIter;
typedef boost::filter_iterator<one_or_four, BaseIter> Iter;
>;
using Iter = boost::filter_iterator<one_or_four, BaseIter>;
boost::function_requires< boost::BidirectionalIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::LvalueIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::BidirectionalTraversalConcept<Iter> >();
}
{
typedef boost::iterator_archetype<
using BaseIter = boost::iterator_archetype<
dummyT
, boost::iterator_archetypes::writable_lvalue_iterator_t
, boost::random_access_traversal_tag
> BaseIter;
typedef boost::filter_iterator<one_or_four, BaseIter> Iter;
>;
using Iter = boost::filter_iterator<one_or_four, BaseIter>;
boost::function_requires< boost::Mutable_BidirectionalIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::WritableIteratorConcept<Iter> >();
boost::function_requires< boost_concepts::LvalueIteratorConcept<Iter> >();
@@ -222,7 +222,7 @@ int main()
dummyT(3), dummyT(4), dummyT(5) };
const int N = sizeof(array)/sizeof(dummyT);
typedef boost::filter_iterator<one_or_four, dummyT*> filter_iter;
using filter_iter = boost::filter_iterator<one_or_four, dummyT*>;
boost::bidirectional_readable_iterator_test(
filter_iter(one_or_four(), array, array+N)
@@ -235,7 +235,13 @@ int main()
>::value,
"Filter interator must have a random_access_traversal_tag.");
//# endif
// Check that the iterator can be constructed from a different but compatible iterator
{
using const_filter_iter = boost::filter_iterator<one_or_four, const dummyT*>;
filter_iter mutable_it(one_or_four(), array+0, array+N);
const_filter_iter const_it(mutable_it);
(void)const_it;
}
// On compilers not supporting partial specialization, we can do more type
// deduction with deque iterators than with pointers... unless the library