forked from boostorg/iterator
Progress on indirect_iterator
[SVN r670]
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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 ;
|
149
test/indirect_iterator_test.cpp
Normal file
149
test/indirect_iterator_test.cpp
Normal 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;
|
||||||
|
}
|
Reference in New Issue
Block a user