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/iterator.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 {
|
||||
|
||||
@@ -100,11 +104,14 @@ typename Base1::difference_type operator-(
|
||||
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
|
||||
// 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
|
||||
@@ -287,42 +294,87 @@ private:
|
||||
|
||||
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>
|
||||
struct traits_of_value_type
|
||||
: detail::iterator_traits<typename detail::iterator_traits<T>::value_type>
|
||||
struct has_element_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
|
||||
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
|
||||
>
|
||||
typedef typename T::element_type& reference;
|
||||
typedef typename T::element_type* pointer;
|
||||
};
|
||||
|
||||
// If the Value parameter is unspecified, we use this metafunction
|
||||
// to deduce the default types
|
||||
template <class Iter>
|
||||
struct indirect_defaults
|
||||
: mpl::if_c<
|
||||
has_element_type<typename iterator_traits<Iter>::value_type>::value
|
||||
, smart_pointer_traits<typename iterator_traits<Iter>::value_type>
|
||||
, 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
|
||||
: iterator_adaptor<
|
||||
indirect_iterator<Base,Value,Reference,Category,Pointer>
|
||||
, Value, Reference, Pointer, Category
|
||||
, typename detail::iterator_traits<Base>::difference_type
|
||||
indirect_iterator<Base,Traits>
|
||||
, typename detail::indirect_traits<Base,Traits>::value_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() {}
|
||||
|
||||
typename detail::indirect_traits<Base,Traits>::reference
|
||||
dereference() const { return **this->m_base; }
|
||||
|
||||
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)
|
||||
template <class Base2, class Traits2>
|
||||
indirect_iterator(const indirect_iterator<Base2,Traits2>& y)
|
||||
: m_base(y.base())
|
||||
{}
|
||||
|
||||
@@ -332,6 +384,18 @@ struct indirect_iterator
|
||||
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
|
||||
|
||||
|
||||
|
@@ -16,6 +16,7 @@
|
||||
#include <boost/iterator/iterator_adaptors.hpp>
|
||||
#include <boost/iterator/iterator_tests.hpp>
|
||||
#include <boost/concept_archetype.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <stdlib.h>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
@@ -35,10 +36,29 @@ struct indirect_iterator_pair_generator
|
||||
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()
|
||||
{
|
||||
// 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);
|
||||
|
||||
@@ -58,13 +78,24 @@ void more_indirect_iterator_tests()
|
||||
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);
|
||||
|
||||
// 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);
|
||||
#endif
|
||||
|
||||
assert(de >= dci);
|
||||
assert(de > dci);
|
||||
|
||||
dci = de;
|
||||
assert(dci == de);
|
||||
|
||||
@@ -73,10 +104,8 @@ void more_indirect_iterator_tests()
|
||||
*db = 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::const_iterator> const_indirect_set_iterator;
|
||||
|
||||
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]);
|
||||
assert(std::equal(db, de, store.begin()));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
@@ -104,45 +131,52 @@ main()
|
||||
dummyT(3), dummyT(4), dummyT(5) };
|
||||
const int N = sizeof(array)/sizeof(dummyT);
|
||||
|
||||
typedef std::deque<boost::shared_ptr<dummyT> > shared_t;
|
||||
shared_t shared;
|
||||
|
||||
// Test indirect_iterator_generator
|
||||
{
|
||||
dummyT* ptr[N];
|
||||
for (int k = 0; k < N; ++k)
|
||||
ptr[k] = array + k;
|
||||
for (int jj = 0; jj < N; ++jj)
|
||||
shared.push_back(boost::shared_ptr<dummyT>(new dummyT(jj)));
|
||||
|
||||
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**> indirect_iterator;
|
||||
|
||||
typedef boost::indirect_iterator<dummyT const* const*
|
||||
#ifdef BOOST_NO_PARTIAL_SPECIALIZATION
|
||||
, dummyT
|
||||
#endif
|
||||
> const_indirect_iterator;
|
||||
typedef boost::indirect_iterator<dummyT const* const*> const_indirect_iterator;
|
||||
|
||||
indirect_iterator i(ptr);
|
||||
boost::random_access_iterator_test(i, N, array);
|
||||
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
|
||||
#if __GNUC__ != 2
|
||||
// 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.
|
||||
|
||||
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->
|
||||
assert((*i).m_x == i->foo());
|
||||
// check operator->
|
||||
assert((*i).m_x == i->foo());
|
||||
|
||||
const_indirect_iterator j(ptr);
|
||||
boost::random_access_iterator_test(j, N, array);
|
||||
const_indirect_iterator j(ptr);
|
||||
boost::random_access_iterator_test(j, N, array);
|
||||
|
||||
|
||||
#if 0 // BOOST_NO_STD_ITERATOR_TRAITS
|
||||
dummyT const*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);
|
||||
dummyT const*const* const_ptr = ptr;
|
||||
boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array);
|
||||
|
||||
boost::const_nonconst_iterator_test(i, ++j);
|
||||
|
||||
more_indirect_iterator_tests();
|
||||
more_indirect_iterator_tests();
|
||||
}
|
||||
std::cout << "test successful " << std::endl;
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user