Progress on indirect_iterator

[SVN r670]
This commit is contained in:
Dave Abrahams
2002-11-07 05:09:44 +00:00
parent ad9df3393d
commit 0157a68e1f
3 changed files with 249 additions and 9 deletions

View File

@@ -46,28 +46,28 @@ template <class Base1, class Base2>
inline bool operator<(const iterator_comparisons<Base1>& xb, inline bool operator<(const iterator_comparisons<Base1>& xb,
const iterator_comparisons<Base2>& yb) const iterator_comparisons<Base2>& yb)
{ {
return xb.self().distance_to(yb.self()) < 0; return xb.self().distance_to(yb.self()) > 0;
} }
template <class Base1, class Base2> template <class Base1, class Base2>
inline bool operator>(const iterator_comparisons<Base1>& xb, inline bool operator>(const iterator_comparisons<Base1>& xb,
const iterator_comparisons<Base2>& yb) const iterator_comparisons<Base2>& yb)
{ {
return xb.self().distance_to(yb.self()) > 0; return xb.self().distance_to(yb.self()) < 0;
} }
template <class Base1, class Base2> template <class Base1, class Base2>
inline bool operator>=(const iterator_comparisons<Base1>& xb, inline bool operator>=(const iterator_comparisons<Base1>& xb,
const iterator_comparisons<Base2>& yb) const iterator_comparisons<Base2>& yb)
{ {
return xb.self().distance_to(yb.self()) >= 0; return xb.self().distance_to(yb.self()) <= 0;
} }
template <class Base1, class Base2> template <class Base1, class Base2>
inline bool operator<=(const iterator_comparisons<Base1>& xb, inline bool operator<=(const iterator_comparisons<Base1>& xb,
const iterator_comparisons<Base2>& yb) const iterator_comparisons<Base2>& yb)
{ {
return xb.self().distance_to(yb.self()) <= 0; return xb.self().distance_to(yb.self()) >= 0;
} }
@@ -97,9 +97,40 @@ typename Base1::difference_type operator-(
const iterator_arith<Base1>& i, const iterator_arith<Base1>& i,
const iterator_arith<Base2>& j) const iterator_arith<Base2>& j)
{ {
return i.self().distance_to(i.self()); return j.self().distance_to(i.self());
} }
#if 0
// Beginnings of a failed attempt to conditionally provide base()
// functions in iterator_adaptor. It may be that a public m_base
// member is the only way to avoid boilerplate!
struct unspecified {};
template <class Base>
struct base_wrapper_impl
{
template <class Super>
struct apply : Super
{
apply() {}
apply(Base b) : m_base(b) {}
Base base() const { return m_base; }
Base& base() { return m_base; }
private:
Base m_base;
};
};
template <>
struct base_wrapper_impl<unspecified>
{
template <class Super>
struct apply : Super
{
};
};
#endif
template <class Final template <class Final
, class V, class R, class P, class C, class D , class V, class R, class P, class C, class D
@@ -117,7 +148,12 @@ struct iterator_adaptor : B
reference operator*() const reference operator*() const
{ return self().dereference(); } { return self().dereference(); }
// Needs eventual help for input iterators
P operator->() const { return &self().dereference(); }
//operator->() const { return detail::operator_arrow(*this, iterator_category()); } //operator->() const { return detail::operator_arrow(*this, iterator_category()); }
reference operator[](difference_type n) const reference operator[](difference_type n) const
{ return *(*this + n); } { return *(*this + n); }
Final& operator++() Final& operator++()
@@ -154,10 +190,10 @@ struct iterator_adaptor : B
difference_type difference_type
distance_to(const iterator_adaptor<Final2,V2,R2,P2,C,D,B2>& y) const distance_to(const iterator_adaptor<Final2,V2,R2,P2,C,D,B2>& y) const
{ {
return self().base() - y.self().base();//? return y.self().base() - self().base();//?
} }
private: // Can't be private, or const/non-const interactions don't work
using B::self; using B::self;
}; };
@@ -242,6 +278,60 @@ private:
AdaptableUnaryFunction m_f; AdaptableUnaryFunction m_f;
}; };
// This macro definition is only temporary in this file
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
# define BOOST_ARG_DEPENDENT_TYPENAME typename
# else
# define BOOST_ARG_DEPENDENT_TYPENAME
# endif
namespace detail
{
template <class T>
struct traits_of_value_type
: detail::iterator_traits<typename detail::iterator_traits<T>::value_type>
{
};
}
template <class Base, // Mutable or Immutable, does not matter
class Value
= BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type<
Base>::value_type
, class Reference
= BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type<
Base>::reference
, class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits<
Base>::iterator_category
, class Pointer
= BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type<
Base>::pointer
>
struct indirect_iterator
: iterator_adaptor<
indirect_iterator<Base,Value,Reference,Category,Pointer>
, Value, Reference, Pointer, Category
, typename detail::iterator_traits<Base>::difference_type
>
{
Reference dereference() const { return **this->m_base; }
indirect_iterator() {}
indirect_iterator(Base iter)
: m_base(iter) {}
template <class Base2, class Reference2, class Pointer2>
indirect_iterator(const indirect_iterator<Base2,Value,Reference2,Category,Pointer2>& y)
: m_base(y.base())
{}
Base& base() { return m_base; }
Base const& base() const { return m_base; }
private:
Base m_base;
};
} // namespace boost } // namespace boost

View File

@@ -2,3 +2,4 @@ SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
include testing.jam ; include testing.jam ;
run iterator_adaptor_cc.cpp ; run iterator_adaptor_cc.cpp ;
run transform_iterator_test.cpp ; run transform_iterator_test.cpp ;
run indirect_iterator_test.cpp ;

View File

@@ -0,0 +1,149 @@
// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
// Revision History
// 08 Mar 2001 Jeremy Siek
// Moved test of indirect iterator into its own file. It to
// to be in iterator_adaptor_test.cpp.
#include <boost/config.hpp>
#include <iostream>
#include <algorithm>
#include <boost/iterator/iterator_adaptors.hpp>
#include <boost/iterator/iterator_tests.hpp>
#include <boost/concept_archetype.hpp>
#include <stdlib.h>
#include <deque>
#include <set>
struct my_iterator_tag : public std::random_access_iterator_tag { };
using boost::dummyT;
typedef std::deque<int> storage;
typedef std::deque<int*> pointer_deque;
typedef std::set<storage::iterator> iterator_set;
template <class Container>
struct indirect_iterator_pair_generator
{
typedef boost::indirect_iterator<typename Container::iterator> iterator;
typedef boost::indirect_iterator<typename Container::const_iterator> const_iterator;
};
void more_indirect_iterator_tests()
{
// For some reason all heck breaks loose in the compiler under these conditions.
#if 1// !defined(BOOST_MSVC) || BOOST_MSVC > 1200 || !defined(__STL_DEBUG)
storage store(1000);
std::generate(store.begin(), store.end(), rand);
pointer_deque ptr_deque;
iterator_set iter_set;
for (storage::iterator p = store.begin(); p != store.end(); ++p)
{
ptr_deque.push_back(&*p);
iter_set.insert(p);
}
typedef indirect_iterator_pair_generator<pointer_deque> IndirectDeque;
IndirectDeque::iterator db(ptr_deque.begin());
IndirectDeque::iterator de(ptr_deque.end());
assert(static_cast<std::size_t>(de - db) == store.size());
assert(db + store.size() == de);
IndirectDeque::const_iterator dci(db);
assert(db == dci);
assert(dci == db);
assert(dci != de);
assert(dci < de);
assert(dci <= de);
assert(de >= dci);
assert(de > dci);
dci = de;
assert(dci == de);
boost::random_access_iterator_test(db + 1, store.size() - 1, boost::next(store.begin()));
*db = 999;
assert(store.front() == 999);
// Borland C++ is getting very confused about the typedef's here
typedef boost::indirect_iterator<iterator_set::iterator> indirect_set_iterator;
typedef boost::indirect_iterator<iterator_set::const_iterator> const_indirect_set_iterator;
indirect_set_iterator sb(iter_set.begin());
indirect_set_iterator se(iter_set.end());
const_indirect_set_iterator sci(iter_set.begin());
assert(sci == sb);
assert(sci != se);
sci = se;
assert(sci == se);
*boost::prior(se) = 888;
assert(store.back() == 888);
assert(std::equal(sb, se, store.begin()));
boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]);
assert(std::equal(db, de, store.begin()));
#endif
}
int
main()
{
dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),
dummyT(3), dummyT(4), dummyT(5) };
const int N = sizeof(array)/sizeof(dummyT);
// Test indirect_iterator_generator
{
dummyT* ptr[N];
for (int k = 0; k < N; ++k)
ptr[k] = array + k;
typedef boost::indirect_iterator<dummyT**
#ifdef BOOST_NO_PARTIAL_SPECIALIZATION
, dummyT
#endif
> indirect_iterator;
typedef boost::indirect_iterator<dummyT* const*
#ifdef BOOST_NO_PARTIAL_SPECIALIZATION
, dummyT
#endif
> const_indirect_iterator;
indirect_iterator i(ptr);
boost::random_access_iterator_test(i, N, array);
#if 0 // BOOST_NO_STD_ITERATOR_TRAITS
boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array);
#endif
// check operator->
assert((*i).m_x == i->foo());
const_indirect_iterator j(ptr);
boost::random_access_iterator_test(j, N, array);
#if 0 // BOOST_NO_STD_ITERATOR_TRAITS
dummyT*const* const_ptr = ptr;
boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array);
#endif
boost::const_nonconst_iterator_test(i, ++j);
more_indirect_iterator_tests();
}
std::cout << "test successful " << std::endl;
return 0;
}