forked from boostorg/iterator
indirect iterators
[SVN r672]
This commit is contained in:
@@ -4,6 +4,10 @@
|
|||||||
#include <boost/utility.hpp> // for prior
|
#include <boost/utility.hpp> // for prior
|
||||||
#include <boost/iterator.hpp>
|
#include <boost/iterator.hpp>
|
||||||
#include <boost/iterator/iterator_categories.hpp>
|
#include <boost/iterator/iterator_categories.hpp>
|
||||||
|
#include <boost/mpl/aux_/has_xxx.hpp>
|
||||||
|
#include <boost/type_traits/is_same.hpp>
|
||||||
|
|
||||||
|
#include "boost/type_traits/detail/bool_trait_def.hpp"
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
|
|
||||||
@@ -100,11 +104,14 @@ typename Base1::difference_type operator-(
|
|||||||
return j.self().distance_to(i.self());
|
return j.self().distance_to(i.self());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used for a default template argument, when we can't afford to
|
||||||
|
// instantiate the default calculation if unused.
|
||||||
|
struct unspecified {};
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Beginnings of a failed attempt to conditionally provide base()
|
// Beginnings of a failed attempt to conditionally provide base()
|
||||||
// functions in iterator_adaptor. It may be that a public m_base
|
// functions in iterator_adaptor. It may be that a public m_base
|
||||||
// member is the only way to avoid boilerplate!
|
// member is the only way to avoid boilerplate!
|
||||||
struct unspecified {};
|
|
||||||
|
|
||||||
template <class Base>
|
template <class Base>
|
||||||
struct base_wrapper_impl
|
struct base_wrapper_impl
|
||||||
@@ -287,42 +294,87 @@ private:
|
|||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// Detection for whether a type has a nested `element_type'
|
||||||
|
// typedef. Used to detect smart pointers. We're having trouble
|
||||||
|
// auto-detecting smart pointers with gcc-2.95 via the nested
|
||||||
|
// element_type member. However, we really ought to have a
|
||||||
|
// specializable is_pointer template which can be used instead with
|
||||||
|
// something like boost/python/pointee.hpp to find the value_type.
|
||||||
|
//
|
||||||
|
namespace aux
|
||||||
|
{
|
||||||
|
BOOST_MPL_HAS_XXX_TRAIT_DEF(element_type)
|
||||||
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct traits_of_value_type
|
struct has_element_type
|
||||||
: detail::iterator_traits<typename detail::iterator_traits<T>::value_type>
|
: mpl::if_<
|
||||||
|
is_class<T>
|
||||||
|
# if __GNUC__ == 2 // gcc 2.95 doesn't seem to be able to detect element_type without barfing
|
||||||
|
, mpl::bool_c<false>
|
||||||
|
# else
|
||||||
|
, aux::has_element_type<T>
|
||||||
|
# endif
|
||||||
|
, mpl::bool_c<false>
|
||||||
|
>::type
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
// Metafunction returning the nested element_type typedef
|
||||||
|
template <class T>
|
||||||
|
struct smart_pointer_traits
|
||||||
|
{
|
||||||
|
typedef typename remove_const<
|
||||||
|
typename T::element_type
|
||||||
|
>::type value_type;
|
||||||
|
|
||||||
template <class Base, // Mutable or Immutable, does not matter
|
typedef typename T::element_type& reference;
|
||||||
class Value
|
typedef typename T::element_type* pointer;
|
||||||
= BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type<
|
};
|
||||||
Base>::value_type
|
|
||||||
, class Reference
|
// If the Value parameter is unspecified, we use this metafunction
|
||||||
= BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type<
|
// to deduce the default types
|
||||||
Base>::reference
|
template <class Iter>
|
||||||
, class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits<
|
struct indirect_defaults
|
||||||
Base>::iterator_category
|
: mpl::if_c<
|
||||||
, class Pointer
|
has_element_type<typename iterator_traits<Iter>::value_type>::value
|
||||||
= BOOST_ARG_DEPENDENT_TYPENAME detail::traits_of_value_type<
|
, smart_pointer_traits<typename iterator_traits<Iter>::value_type>
|
||||||
Base>::pointer
|
, iterator_traits<typename iterator_traits<Iter>::value_type>
|
||||||
>
|
>::type
|
||||||
|
{
|
||||||
|
typedef typename iterator_traits<Iter>::iterator_category iterator_category;
|
||||||
|
typedef typename iterator_traits<Iter>::difference_type difference_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Base, class Traits>
|
||||||
|
struct indirect_traits
|
||||||
|
: mpl::if_<is_same<Traits,unspecified>, indirect_defaults<Base>, Traits>::type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <class Base, class Traits = unspecified>
|
||||||
struct indirect_iterator
|
struct indirect_iterator
|
||||||
: iterator_adaptor<
|
: iterator_adaptor<
|
||||||
indirect_iterator<Base,Value,Reference,Category,Pointer>
|
indirect_iterator<Base,Traits>
|
||||||
, Value, Reference, Pointer, Category
|
, typename detail::indirect_traits<Base,Traits>::value_type
|
||||||
, typename detail::iterator_traits<Base>::difference_type
|
, typename detail::indirect_traits<Base,Traits>::reference
|
||||||
|
, typename detail::indirect_traits<Base,Traits>::pointer
|
||||||
|
, typename detail::indirect_traits<Base,Traits>::iterator_category
|
||||||
|
, typename detail::indirect_traits<Base,Traits>::difference_type
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
Reference dereference() const { return **this->m_base; }
|
|
||||||
|
|
||||||
indirect_iterator() {}
|
indirect_iterator() {}
|
||||||
|
|
||||||
|
typename detail::indirect_traits<Base,Traits>::reference
|
||||||
|
dereference() const { return **this->m_base; }
|
||||||
|
|
||||||
indirect_iterator(Base iter)
|
indirect_iterator(Base iter)
|
||||||
: m_base(iter) {}
|
: m_base(iter) {}
|
||||||
|
|
||||||
template <class Base2, class Reference2, class Pointer2>
|
template <class Base2, class Traits2>
|
||||||
indirect_iterator(const indirect_iterator<Base2,Value,Reference2,Category,Pointer2>& y)
|
indirect_iterator(const indirect_iterator<Base2,Traits2>& y)
|
||||||
: m_base(y.base())
|
: m_base(y.base())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -332,6 +384,18 @@ struct indirect_iterator
|
|||||||
Base m_base;
|
Base m_base;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class Iter>
|
||||||
|
indirect_iterator<Iter> make_indirect_iterator(Iter x)
|
||||||
|
{
|
||||||
|
return indirect_iterator<Iter>(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Traits, class Iter>
|
||||||
|
indirect_iterator<Iter,Traits> make_indirect_iterator(Iter x, Traits* = 0)
|
||||||
|
{
|
||||||
|
return indirect_iterator<Iter,Traits>(x);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
|
||||||
|
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
#include <boost/iterator/iterator_adaptors.hpp>
|
#include <boost/iterator/iterator_adaptors.hpp>
|
||||||
#include <boost/iterator/iterator_tests.hpp>
|
#include <boost/iterator/iterator_tests.hpp>
|
||||||
#include <boost/concept_archetype.hpp>
|
#include <boost/concept_archetype.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <set>
|
#include <set>
|
||||||
@@ -35,10 +36,29 @@ struct indirect_iterator_pair_generator
|
|||||||
typedef boost::indirect_iterator<typename Container::const_iterator> const_iterator;
|
typedef boost::indirect_iterator<typename Container::const_iterator> const_iterator;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
namespace boost { namespace detail
|
||||||
|
{
|
||||||
|
template<> struct iterator_traits<int*>
|
||||||
|
: ptr_iter_traits<int> {};
|
||||||
|
|
||||||
|
template<> struct iterator_traits<dummyT*>
|
||||||
|
: ptr_iter_traits<dummyT> {};
|
||||||
|
|
||||||
|
template<> struct iterator_traits<dummyT const*>
|
||||||
|
: ptr_iter_traits<dummyT, dummyT const> {};
|
||||||
|
|
||||||
|
template<> struct iterator_traits<dummyT**>
|
||||||
|
: ptr_iter_traits<dummyT*> {};
|
||||||
|
|
||||||
|
template<> struct iterator_traits<dummyT const*const*>
|
||||||
|
: ptr_iter_traits<dummyT const*, dummyT const*const> {};
|
||||||
|
}}
|
||||||
|
#endif
|
||||||
|
|
||||||
void more_indirect_iterator_tests()
|
void more_indirect_iterator_tests()
|
||||||
{
|
{
|
||||||
// For some reason all heck breaks loose in the compiler under these conditions.
|
// 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);
|
storage store(1000);
|
||||||
std::generate(store.begin(), store.end(), rand);
|
std::generate(store.begin(), store.end(), rand);
|
||||||
|
|
||||||
@@ -58,13 +78,24 @@ void more_indirect_iterator_tests()
|
|||||||
assert(static_cast<std::size_t>(de - db) == store.size());
|
assert(static_cast<std::size_t>(de - db) == store.size());
|
||||||
assert(db + store.size() == de);
|
assert(db + store.size() == de);
|
||||||
IndirectDeque::const_iterator dci(db);
|
IndirectDeque::const_iterator dci(db);
|
||||||
assert(db == dci);
|
|
||||||
assert(dci == db);
|
assert(dci == db);
|
||||||
|
|
||||||
|
// Older Dinkumware and GCC standard lib don't supply symmetric constant/mutable
|
||||||
|
// iterator operators
|
||||||
|
#if !defined(BOOST_MSVC_STD_ITERATOR) && (!defined(_CPPLIB_VER) || _CPPLIB_VER > 310) \
|
||||||
|
&& (__GNUC__ != 2 || defined(__SGI_STL_PORT))
|
||||||
|
|
||||||
|
assert(db == dci);
|
||||||
|
|
||||||
assert(dci != de);
|
assert(dci != de);
|
||||||
assert(dci < de);
|
assert(dci < de);
|
||||||
assert(dci <= de);
|
assert(dci <= de);
|
||||||
|
#endif
|
||||||
|
|
||||||
assert(de >= dci);
|
assert(de >= dci);
|
||||||
assert(de > dci);
|
assert(de > dci);
|
||||||
|
|
||||||
dci = de;
|
dci = de;
|
||||||
assert(dci == de);
|
assert(dci == de);
|
||||||
|
|
||||||
@@ -73,10 +104,8 @@ void more_indirect_iterator_tests()
|
|||||||
*db = 999;
|
*db = 999;
|
||||||
assert(store.front() == 999);
|
assert(store.front() == 999);
|
||||||
|
|
||||||
// Borland C++ is getting very confused about the typedef's here
|
// Borland C++ is getting very confused about the typedefs here
|
||||||
|
|
||||||
typedef boost::indirect_iterator<iterator_set::iterator> indirect_set_iterator;
|
typedef boost::indirect_iterator<iterator_set::iterator> indirect_set_iterator;
|
||||||
|
|
||||||
typedef boost::indirect_iterator<iterator_set::const_iterator> const_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 sb(iter_set.begin());
|
||||||
@@ -93,8 +122,6 @@ void more_indirect_iterator_tests()
|
|||||||
|
|
||||||
boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]);
|
boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]);
|
||||||
assert(std::equal(db, de, store.begin()));
|
assert(std::equal(db, de, store.begin()));
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -104,45 +131,52 @@ main()
|
|||||||
dummyT(3), dummyT(4), dummyT(5) };
|
dummyT(3), dummyT(4), dummyT(5) };
|
||||||
const int N = sizeof(array)/sizeof(dummyT);
|
const int N = sizeof(array)/sizeof(dummyT);
|
||||||
|
|
||||||
|
typedef std::deque<boost::shared_ptr<dummyT> > shared_t;
|
||||||
|
shared_t shared;
|
||||||
|
|
||||||
// Test indirect_iterator_generator
|
// Test indirect_iterator_generator
|
||||||
{
|
{
|
||||||
dummyT* ptr[N];
|
for (int jj = 0; jj < N; ++jj)
|
||||||
for (int k = 0; k < N; ++k)
|
shared.push_back(boost::shared_ptr<dummyT>(new dummyT(jj)));
|
||||||
ptr[k] = array + k;
|
|
||||||
|
dummyT* ptr[N];
|
||||||
|
for (int k = 0; k < N; ++k)
|
||||||
|
ptr[k] = array + k;
|
||||||
|
|
||||||
typedef boost::indirect_iterator<dummyT**
|
typedef boost::indirect_iterator<dummyT**> indirect_iterator;
|
||||||
#ifdef BOOST_NO_PARTIAL_SPECIALIZATION
|
|
||||||
, dummyT
|
|
||||||
#endif
|
|
||||||
> indirect_iterator;
|
|
||||||
|
|
||||||
typedef boost::indirect_iterator<dummyT const* const*
|
typedef boost::indirect_iterator<dummyT const* const*> const_indirect_iterator;
|
||||||
#ifdef BOOST_NO_PARTIAL_SPECIALIZATION
|
|
||||||
, dummyT
|
|
||||||
#endif
|
|
||||||
> const_indirect_iterator;
|
|
||||||
|
|
||||||
indirect_iterator i(ptr);
|
indirect_iterator i(ptr);
|
||||||
boost::random_access_iterator_test(i, N, array);
|
boost::random_access_iterator_test(i, N, array);
|
||||||
|
|
||||||
#if 0 // BOOST_NO_STD_ITERATOR_TRAITS
|
#if __GNUC__ != 2
|
||||||
boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array);
|
// We're having trouble auto-detecting smart pointers with
|
||||||
#endif
|
// gcc-2.95 via the nested element_type member. However, we
|
||||||
|
// really ought to have a specializable is_pointer template
|
||||||
|
// which can be used instead with something like
|
||||||
|
// boost/python/pointee.hpp to find the value_type.
|
||||||
|
|
||||||
|
boost::random_access_iterator_test(
|
||||||
|
boost::indirect_iterator<shared_t::iterator>(shared.begin())
|
||||||
|
, N, array);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array);
|
||||||
|
|
||||||
// check operator->
|
// check operator->
|
||||||
assert((*i).m_x == i->foo());
|
assert((*i).m_x == i->foo());
|
||||||
|
|
||||||
const_indirect_iterator j(ptr);
|
const_indirect_iterator j(ptr);
|
||||||
boost::random_access_iterator_test(j, N, array);
|
boost::random_access_iterator_test(j, N, array);
|
||||||
|
|
||||||
|
|
||||||
#if 0 // BOOST_NO_STD_ITERATOR_TRAITS
|
dummyT const*const* const_ptr = ptr;
|
||||||
dummyT const*const* const_ptr = ptr;
|
boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array);
|
||||||
boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array);
|
|
||||||
#endif
|
boost::const_nonconst_iterator_test(i, ++j);
|
||||||
boost::const_nonconst_iterator_test(i, ++j);
|
|
||||||
|
|
||||||
more_indirect_iterator_tests();
|
more_indirect_iterator_tests();
|
||||||
}
|
}
|
||||||
std::cout << "test successful " << std::endl;
|
std::cout << "test successful " << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
|
Reference in New Issue
Block a user