forked from boostorg/iterator
Fix indirect iterators for broken compilers
[SVN r843]
This commit is contained in:
@@ -7,14 +7,19 @@
|
|||||||
#include <boost/iterator.hpp>
|
#include <boost/iterator.hpp>
|
||||||
#include <boost/detail/workaround.hpp>
|
#include <boost/detail/workaround.hpp>
|
||||||
#include <boost/iterator/iterator_categories.hpp>
|
#include <boost/iterator/iterator_categories.hpp>
|
||||||
|
|
||||||
#include <boost/mpl/aux_/has_xxx.hpp>
|
#include <boost/mpl/aux_/has_xxx.hpp>
|
||||||
#include <boost/mpl/logical/or.hpp>
|
#include <boost/mpl/logical/or.hpp>
|
||||||
|
#include <boost/mpl/identity.hpp>
|
||||||
|
|
||||||
#include <boost/type_traits/is_same.hpp>
|
#include <boost/type_traits/is_same.hpp>
|
||||||
#include <boost/type_traits/is_convertible.hpp>
|
#include <boost/type_traits/is_convertible.hpp>
|
||||||
|
|
||||||
#include "boost/type_traits/detail/bool_trait_def.hpp"
|
#include "boost/type_traits/detail/bool_trait_def.hpp"
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1301) || BOOST_WORKAROUND(__GNUC__, <= 2 && __GNUC_MINOR__ <= 95) || BOOST_WORKAROUND(__MWERKS__, <= 0x3000)
|
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1301) \
|
||||||
|
|| BOOST_WORKAROUND(__GNUC__, <= 2 && __GNUC_MINOR__ <= 95) \
|
||||||
|
|| BOOST_WORKAROUND(__MWERKS__, <= 0x3000)
|
||||||
# define BOOST_NO_SFINAE // "Substitution Failure Is Not An Error not implemented"
|
# define BOOST_NO_SFINAE // "Substitution Failure Is Not An Error not implemented"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -25,9 +30,21 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
|
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
|
||||||
# define BOOST_NO_IS_CONVERTIBLE // "Convertible does not provide enough/is not working"
|
# define BOOST_NO_IS_CONVERTIBLE // "is_convertible doesn't work"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if BOOST_WORKAROUND(__GNUC__, == 2 && __GNUC_MINOR__ == 95) \
|
||||||
|
|| BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||||
|
# define BOOST_NO_MPL_AUX_HAS_XXX // "MPL's has_xxx facility doesn't work"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BOOST_NO_MPL_AUX_HAS_XXX
|
||||||
|
# include <boost/shared_ptr.hpp>
|
||||||
|
# include <boost/scoped_ptr.hpp>
|
||||||
|
# include <memory>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@@ -86,12 +103,12 @@ namespace boost {
|
|||||||
// on operator implementation for consequences.
|
// on operator implementation for consequences.
|
||||||
//
|
//
|
||||||
template <typename A, typename B>
|
template <typename A, typename B>
|
||||||
struct is_interoperable :
|
struct is_interoperable
|
||||||
#ifdef BOOST_NO_IS_CONVERTIBLE
|
#ifdef BOOST_NO_IS_CONVERTIBLE
|
||||||
mpl::true_c
|
: mpl::true_c
|
||||||
#else
|
#else
|
||||||
mpl::logical_or< is_convertible< A, B >,
|
: mpl::logical_or< is_convertible< A, B >,
|
||||||
is_convertible< B, A > >
|
is_convertible< B, A > >
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
@@ -105,12 +122,16 @@ namespace boost {
|
|||||||
template <class Facade1,
|
template <class Facade1,
|
||||||
class Facade2,
|
class Facade2,
|
||||||
class Return>
|
class Return>
|
||||||
struct enable_if_interoperable :
|
struct enable_if_interoperable
|
||||||
enabled< is_interoperable<Facade1, Facade2>::value >::template base<Return>
|
# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE)
|
||||||
|
: enabled< is_interoperable<Facade1, Facade2>::value >::template base<Return>
|
||||||
|
# else
|
||||||
|
: mpl::identity<Return>
|
||||||
|
# endif
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(BOOST_MSVC, <=1200)
|
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
|
||||||
typedef typename enabled< is_interoperable<Facade1, Facade2>::value >::template base<Return>::type type;
|
typedef Return type;
|
||||||
#endif
|
# endif
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -161,24 +182,19 @@ namespace boost {
|
|||||||
// false positives for user/library defined iterator types. See comments
|
// false positives for user/library defined iterator types. See comments
|
||||||
// on operator implementation for consequences.
|
// on operator implementation for consequences.
|
||||||
//
|
//
|
||||||
#ifdef BOOST_NO_IS_CONVERTIBLE
|
|
||||||
template<typename From,
|
template<typename From,
|
||||||
typename To>
|
typename To>
|
||||||
struct enable_if_convertible
|
struct enable_if_convertible
|
||||||
{
|
#if !defined(BOOST_NO_IS_CONVERTIBLE) && !defined(BOOST_NO_SFINAE)
|
||||||
typedef detail::enable_type type;
|
: detail::enabled< is_convertible<From, To>::value >::template base<detail::enable_type>
|
||||||
};
|
|
||||||
#else
|
#else
|
||||||
template<typename From,
|
: mpl::identity<detail::enable_type>
|
||||||
typename To>
|
#endif
|
||||||
struct enable_if_convertible :
|
|
||||||
detail::enabled< is_convertible<From, To>::value >::template base<detail::enable_type>
|
|
||||||
{
|
{
|
||||||
#if BOOST_WORKAROUND(BOOST_MSVC, <=1200)
|
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
|
||||||
typedef typename detail::enabled< is_convertible<From, To>::value >::template base<detail::enable_type>::type type;
|
typedef detail::enable_type type;
|
||||||
#endif
|
# endif
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Helper class for granting access to the iterator core interface.
|
// Helper class for granting access to the iterator core interface.
|
||||||
@@ -708,31 +724,44 @@ namespace boost {
|
|||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Detection for whether a type has a nested `element_type'
|
// Detection for whether a type has a nested `element_type'
|
||||||
// typedef. Used to detect smart pointers. We're having trouble
|
// typedef. Used to detect smart pointers. For compilers not
|
||||||
// auto-detecting smart pointers with gcc-2.95 via the nested
|
// supporting mpl's has_xxx, we supply specialzations. However, we
|
||||||
// element_type member. However, we really ought to have a
|
// really ought to have a specializable is_pointer template which
|
||||||
// specializable is_pointer template which can be used instead with
|
// can be used instead with something like
|
||||||
// something like boost/python/pointee.hpp to find the value_type.
|
// boost/python/pointee.hpp to find the value_type.
|
||||||
//
|
//
|
||||||
|
# if !defined BOOST_NO_MPL_AUX_HAS_XXX
|
||||||
namespace aux
|
namespace aux
|
||||||
{
|
{
|
||||||
BOOST_MPL_HAS_XXX_TRAIT_DEF(element_type)
|
BOOST_MPL_HAS_XXX_TRAIT_DEF(element_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct has_element_type
|
struct has_element_type
|
||||||
: mpl::if_<
|
: mpl::if_<
|
||||||
is_class<T>
|
is_class<T>
|
||||||
// gcc 2.95 doesn't seem to be able to detect element_type without barfing
|
, aux::has_element_type<T>
|
||||||
# if BOOST_WORKAROUND(__GNUC__, == 2 && __GNUC_MINOR__ == 95)
|
, mpl::false_c
|
||||||
, mpl::bool_c<false>
|
>::type
|
||||||
# else
|
|
||||||
, aux::has_element_type<T>
|
|
||||||
# endif
|
|
||||||
, mpl::bool_c<false>
|
|
||||||
>::type
|
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
# else
|
||||||
|
template <class T>
|
||||||
|
struct has_element_type
|
||||||
|
: mpl::false_c {};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct has_element_type<boost::shared_ptr<T> >
|
||||||
|
: mpl::true_c {};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct has_element_type<boost::scoped_ptr<T> >
|
||||||
|
: mpl::true_c {};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct has_element_type<std::auto_ptr<T> >
|
||||||
|
: mpl::true_c {};
|
||||||
|
# endif
|
||||||
|
|
||||||
// Metafunction returning the nested element_type typedef
|
// Metafunction returning the nested element_type typedef
|
||||||
template <class T>
|
template <class T>
|
||||||
@@ -750,11 +779,11 @@ namespace boost {
|
|||||||
// to deduce the default types
|
// to deduce the default types
|
||||||
template <class Iter>
|
template <class Iter>
|
||||||
struct indirect_defaults
|
struct indirect_defaults
|
||||||
: mpl::if_c<
|
: mpl::if_<
|
||||||
has_element_type<typename iterator_traits<Iter>::value_type>::value
|
has_element_type<typename iterator_traits<Iter>::value_type>
|
||||||
, smart_pointer_traits<typename iterator_traits<Iter>::value_type>
|
, smart_pointer_traits<typename iterator_traits<Iter>::value_type>
|
||||||
, iterator_traits<typename iterator_traits<Iter>::value_type>
|
, iterator_traits<typename iterator_traits<Iter>::value_type>
|
||||||
>::type
|
>::type
|
||||||
{
|
{
|
||||||
typedef typename iterator_traits<Iter>::iterator_category iterator_category;
|
typedef typename iterator_traits<Iter>::iterator_category iterator_category;
|
||||||
typedef typename iterator_traits<Iter>::difference_type difference_type;
|
typedef typename iterator_traits<Iter>::difference_type difference_type;
|
||||||
@@ -824,14 +853,9 @@ namespace boost {
|
|||||||
// clean up local workaround macros
|
// clean up local workaround macros
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifdef BOOST_NO_SFINAE
|
#undef BOOST_NO_SFINAE
|
||||||
# undef BOOST_NO_SFINAE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#undef BOOST_ARG_DEP_TYPENAME
|
#undef BOOST_ARG_DEP_TYPENAME
|
||||||
|
#undef BOOST_NO_IS_CONVERTIBLE
|
||||||
#ifdef BOOST_NO_IS_CONVERTIBLE
|
#undef BOOST_NO_MPL_AUX_HAS_XXX
|
||||||
# undef BOOST_NO_IS_CONVERTIBLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // BOOST_ITERATOR_ADAPTORS_HPP
|
#endif // BOOST_ITERATOR_ADAPTORS_HPP
|
||||||
|
@@ -26,22 +26,64 @@
|
|||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <deque>
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
#if defined(BOOST_MSVC_STD_ITERATOR) \
|
||||||
|
|| BOOST_WORKAROUND(_CPPLIB_VER, <= 310) \
|
||||||
|
|| BOOST_WORKAROUND(__GNUC__, <= 2 && !defined(__SGI_STL_PORT))
|
||||||
|
|
||||||
|
// std container random-access iterators don't support mutable/const
|
||||||
|
// interoperability (but may support const/mutable interop).
|
||||||
|
# define NO_MUTABLE_CONST_STD_DEQUE_ITERATOR_INTEROPERABILITY
|
||||||
|
# define NO_MUTABLE_CONST_STD_SET_ITERATOR_INTEROPERABILITY
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(BOOST_MSVC_STD_ITERATOR) \
|
||||||
|
|| defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||||
|
|
||||||
|
// No working iterator_traits implementation, so we must use deque
|
||||||
|
# define RA_CONTAINER std::deque
|
||||||
|
# include <deque>
|
||||||
|
|
||||||
|
# ifdef NO_MUTABLE_CONST_STD_DEQUE_ITERATOR_INTEROPERABILITY
|
||||||
|
# define NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# define RA_CONTAINER std::vector
|
||||||
|
# include <vector>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
struct my_iterator_tag : public std::random_access_iterator_tag { };
|
struct my_iterator_tag : public std::random_access_iterator_tag { };
|
||||||
|
|
||||||
using boost::dummyT;
|
using boost::dummyT;
|
||||||
|
|
||||||
typedef std::deque<int> storage;
|
typedef RA_CONTAINER<int> storage;
|
||||||
typedef std::deque<int*> pointer_deque;
|
typedef RA_CONTAINER<int*> pointer_ra_container;
|
||||||
typedef std::set<storage::iterator> iterator_set;
|
typedef std::set<storage::iterator> iterator_set;
|
||||||
|
|
||||||
|
// Something has to be done about putting this in the lib
|
||||||
|
template <class Iter>
|
||||||
|
struct indirect_const_iterator_traits
|
||||||
|
: boost::detail::indirect_defaults<Iter>
|
||||||
|
{
|
||||||
|
typedef boost::detail::indirect_defaults<Iter> base;
|
||||||
|
typedef typename base::value_type const& reference;
|
||||||
|
typedef typename base::value_type const* pointer;
|
||||||
|
};
|
||||||
|
|
||||||
template <class Container>
|
template <class Container>
|
||||||
struct indirect_iterator_pair_generator
|
struct indirect_iterator_pair_generator
|
||||||
{
|
{
|
||||||
typedef boost::indirect_iterator<typename Container::iterator> iterator;
|
typedef boost::indirect_iterator<typename Container::iterator> iterator;
|
||||||
typedef boost::indirect_iterator<typename Container::const_iterator> const_iterator;
|
|
||||||
|
typedef boost::indirect_iterator<
|
||||||
|
typename Container::iterator
|
||||||
|
, indirect_const_iterator_traits<typename Container::iterator>
|
||||||
|
> const_iterator;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
@@ -70,40 +112,37 @@ void more_indirect_iterator_tests()
|
|||||||
storage store(1000);
|
storage store(1000);
|
||||||
std::generate(store.begin(), store.end(), rand);
|
std::generate(store.begin(), store.end(), rand);
|
||||||
|
|
||||||
pointer_deque ptr_deque;
|
pointer_ra_container ptr_ra_container;
|
||||||
iterator_set iter_set;
|
iterator_set iter_set;
|
||||||
|
|
||||||
for (storage::iterator p = store.begin(); p != store.end(); ++p)
|
for (storage::iterator p = store.begin(); p != store.end(); ++p)
|
||||||
{
|
{
|
||||||
ptr_deque.push_back(&*p);
|
ptr_ra_container.push_back(&*p);
|
||||||
iter_set.insert(p);
|
iter_set.insert(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef indirect_iterator_pair_generator<pointer_deque> IndirectDeque;
|
typedef indirect_iterator_pair_generator<pointer_ra_container> indirect_ra_container;
|
||||||
|
|
||||||
IndirectDeque::iterator db(ptr_deque.begin());
|
indirect_ra_container::iterator db(ptr_ra_container.begin());
|
||||||
IndirectDeque::iterator de(ptr_deque.end());
|
indirect_ra_container::iterator de(ptr_ra_container.end());
|
||||||
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);
|
indirect_ra_container::const_iterator dci = db;
|
||||||
|
|
||||||
assert(dci == db);
|
assert(dci == db);
|
||||||
|
|
||||||
// Older Dinkumware and GCC standard lib don't supply symmetric constant/mutable
|
#ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY
|
||||||
// iterator operators
|
|
||||||
#if !defined(BOOST_MSVC_STD_ITERATOR) \
|
|
||||||
&& !BOOST_WORKAROUND(_CPPLIB_VER, <= 310) \
|
|
||||||
&& !BOOST_WORKAROUND(__GNUC__, <= 2 && !defined(__SGI_STL_PORT))
|
|
||||||
|
|
||||||
assert(db == dci);
|
assert(db == dci);
|
||||||
|
#endif
|
||||||
|
|
||||||
assert(dci != de);
|
assert(dci != de);
|
||||||
assert(dci < de);
|
assert(dci < de);
|
||||||
assert(dci <= de);
|
assert(dci <= de);
|
||||||
#endif
|
|
||||||
|
|
||||||
|
#ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY
|
||||||
assert(de >= dci);
|
assert(de >= dci);
|
||||||
assert(de > dci);
|
assert(de > dci);
|
||||||
|
#endif
|
||||||
|
|
||||||
dci = de;
|
dci = de;
|
||||||
assert(dci == de);
|
assert(dci == de);
|
||||||
@@ -121,6 +160,11 @@ void more_indirect_iterator_tests()
|
|||||||
indirect_set_iterator se(iter_set.end());
|
indirect_set_iterator se(iter_set.end());
|
||||||
const_indirect_set_iterator sci(iter_set.begin());
|
const_indirect_set_iterator sci(iter_set.begin());
|
||||||
assert(sci == sb);
|
assert(sci == sb);
|
||||||
|
|
||||||
|
# ifndef NO_MUTABLE_CONST_STD_SET_ITERATOR_INTEROPERABILITY
|
||||||
|
assert(se != sci);
|
||||||
|
# endif
|
||||||
|
|
||||||
assert(sci != se);
|
assert(sci != se);
|
||||||
sci = se;
|
sci = se;
|
||||||
assert(sci == se);
|
assert(sci == se);
|
||||||
@@ -140,7 +184,7 @@ 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;
|
typedef RA_CONTAINER<boost::shared_ptr<dummyT> > shared_t;
|
||||||
shared_t shared;
|
shared_t shared;
|
||||||
|
|
||||||
// Concept checks
|
// Concept checks
|
||||||
@@ -148,12 +192,9 @@ main()
|
|||||||
typedef boost::indirect_iterator<shared_t::iterator> iter_t;
|
typedef boost::indirect_iterator<shared_t::iterator> iter_t;
|
||||||
typedef boost::indirect_iterator<shared_t::const_iterator> c_iter_t;
|
typedef boost::indirect_iterator<shared_t::const_iterator> c_iter_t;
|
||||||
|
|
||||||
// Older Dinkumware and GCC standard lib don't supply symmetric constant/mutable
|
# ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY
|
||||||
// iterator operators
|
|
||||||
#if !defined(BOOST_MSVC_STD_ITERATOR) && (!defined(_CPPLIB_VER) || _CPPLIB_VER > 310) \
|
|
||||||
&& (__GNUC__ != 2 || defined(__SGI_STL_PORT))
|
|
||||||
boost::function_requires< boost_concepts::InteroperableConcept<iter_t, c_iter_t> >();
|
boost::function_requires< boost_concepts::InteroperableConcept<iter_t, c_iter_t> >();
|
||||||
#endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test indirect_iterator_generator
|
// Test indirect_iterator_generator
|
||||||
@@ -167,22 +208,15 @@ main()
|
|||||||
|
|
||||||
typedef boost::indirect_iterator<dummyT**> indirect_iterator;
|
typedef boost::indirect_iterator<dummyT**> indirect_iterator;
|
||||||
|
|
||||||
typedef boost::indirect_iterator<dummyT const* const*> const_indirect_iterator;
|
typedef boost::indirect_iterator<dummyT**, indirect_const_iterator_traits<dummyT**> >
|
||||||
|
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 __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::random_access_iterator_test(
|
||||||
boost::indirect_iterator<shared_t::iterator>(shared.begin())
|
boost::indirect_iterator<shared_t::iterator>(shared.begin())
|
||||||
, N, array);
|
, N, array);
|
||||||
#endif
|
|
||||||
|
|
||||||
boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array);
|
boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user