mirror of https://github.com/CGAL/cgal
Refactor circulators a little
Give a name proper name to meta-functions that are not used outside Circulator and enable conversion between circulator tags.
This commit is contained in:
parent
f15cf44e06
commit
e623040728
|
|
@ -26,11 +26,15 @@
|
|||
#define CGAL_CIRCULATOR_H
|
||||
|
||||
#include <CGAL/basic.h>
|
||||
#include <CGAL/circulator_bases.h>
|
||||
#include <CGAL/use.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <CGAL/circulator_bases.h>
|
||||
#include <CGAL/use.h>
|
||||
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
// These are name redefinitions for backwards compatibility
|
||||
// with the pre iterator-traits style adaptors.
|
||||
|
|
@ -73,25 +77,27 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
template <class C>
|
||||
struct I_Circulator_traits {
|
||||
typedef Iterator_tag category;
|
||||
};
|
||||
namespace internal {
|
||||
|
||||
template <>
|
||||
struct I_Circulator_traits<Forward_circulator_tag> {
|
||||
typedef Circulator_tag category;
|
||||
};
|
||||
// default to Iterator_tag, special case Circulator tags
|
||||
template<typename Tag>
|
||||
struct Get_category
|
||||
{ typedef Iterator_tag type; };
|
||||
|
||||
template <>
|
||||
struct I_Circulator_traits<Bidirectional_circulator_tag> {
|
||||
typedef Circulator_tag category;
|
||||
};
|
||||
template<>
|
||||
struct Get_category<CGAL::Forward_circulator_tag>
|
||||
{ typedef Circulator_tag type; };
|
||||
|
||||
template<>
|
||||
struct Get_category<CGAL::Bidirectional_circulator_tag>
|
||||
{ typedef Circulator_tag type; };
|
||||
|
||||
template<>
|
||||
struct Get_category<CGAL::Random_access_circulator_tag>
|
||||
{ typedef Circulator_tag type; };
|
||||
|
||||
} // internal
|
||||
|
||||
template <>
|
||||
struct I_Circulator_traits<Random_access_circulator_tag> {
|
||||
typedef Circulator_tag category;
|
||||
};
|
||||
|
||||
// Circulator_size_traits are used by general adaptors for
|
||||
// iterators and circulators. For example the N_step_adaptor
|
||||
|
|
@ -163,16 +169,24 @@ struct I_Circulator_from_iterator_traits<std::random_access_iterator_tag> {
|
|||
|
||||
template <class C>
|
||||
struct Circulator_traits {
|
||||
typedef std::iterator_traits<C> traits;
|
||||
typedef typename traits::iterator_category ICAT;
|
||||
typedef I_Circulator_traits<ICAT> C_traits;
|
||||
typedef typename C_traits::category category;
|
||||
private:
|
||||
typedef std::iterator_traits<C> iterator_traits;
|
||||
public:
|
||||
// the ardent reader might wonder: why redirect through
|
||||
// iterator_traits? That way we don't miss specializations and
|
||||
// can save us our own specializations.
|
||||
typedef typename internal::Get_category<
|
||||
typename iterator_traits::iterator_category
|
||||
>::type category;
|
||||
|
||||
typedef I_Iterator_from_circulator_traits<ICAT> Ic_traits;
|
||||
typedef typename Ic_traits::iterator_category iterator_category;
|
||||
typedef typename iterator_traits::value_type value_type;
|
||||
typedef typename iterator_traits::reference reference;
|
||||
typedef typename iterator_traits::pointer pointer;
|
||||
typedef typename iterator_traits::difference_type difference_type;
|
||||
typedef typename iterator_traits::iterator_category iterator_category;
|
||||
|
||||
typedef I_Circulator_from_iterator_traits<ICAT> Ci_traits;
|
||||
typedef typename Ci_traits::iterator_category circulator_category;
|
||||
typedef typename I_Circulator_size_traits<
|
||||
category, C>::size_type size_type;
|
||||
};
|
||||
|
||||
template <class C>
|
||||
|
|
@ -181,64 +195,44 @@ query_circulator_or_iterator( const C&) {
|
|||
typedef typename Circulator_traits<C>::category category;
|
||||
return category();
|
||||
}
|
||||
/* A function that asserts a specific compile time tag */
|
||||
/* forcing its two arguments to have equal type. */
|
||||
/* It is encapsulated with #ifdef since it will be defined also elsewhere. */
|
||||
#ifndef CGAL_ASSERT_COMPILE_TIME_TAG
|
||||
#define CGAL_ASSERT_COMPILE_TIME_TAG 1
|
||||
template <class Base>
|
||||
struct I_Assert_tag_class {
|
||||
void match_compile_time_tag( const Base&) const {}
|
||||
};
|
||||
template< class Tag, class Derived>
|
||||
inline void Assert_compile_time_tag( const Tag&, const Derived& b) {
|
||||
I_Assert_tag_class<Tag> x;
|
||||
x.match_compile_time_tag(b);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class C> inline
|
||||
void Assert_circulator( const C &) {
|
||||
typedef typename Circulator_traits<C>::category category;
|
||||
Assert_compile_time_tag( Circulator_tag(), category());
|
||||
BOOST_STATIC_ASSERT((boost::is_convertible<category, Circulator_tag>::value));
|
||||
}
|
||||
|
||||
template <class I> inline
|
||||
void Assert_iterator( const I &) {
|
||||
typedef typename Circulator_traits<I>::category category;
|
||||
Assert_compile_time_tag( Iterator_tag(), category());
|
||||
BOOST_STATIC_ASSERT((boost::is_convertible<category, Iterator_tag>::value));
|
||||
}
|
||||
template <class I> inline
|
||||
void Assert_input_category( const I &/*i*/) {
|
||||
typedef typename std::iterator_traits<I>::iterator_category category;
|
||||
Assert_compile_time_tag( std::input_iterator_tag(),
|
||||
category());
|
||||
BOOST_STATIC_ASSERT((boost::is_convertible<category, std::input_iterator_tag>::value));
|
||||
}
|
||||
|
||||
template <class I> inline
|
||||
void Assert_output_category( const I &/*i*/) {
|
||||
typedef typename std::iterator_traits<I>::iterator_category category;
|
||||
Assert_compile_time_tag( std::output_iterator_tag(),
|
||||
category());
|
||||
BOOST_STATIC_ASSERT((boost::is_convertible<category, std::output_iterator_tag>::value));
|
||||
}
|
||||
template <class IC> inline
|
||||
void Assert_forward_category( const IC &/*ic*/) {
|
||||
typedef typename std::iterator_traits<IC>::iterator_category category;
|
||||
Assert_compile_time_tag( std::forward_iterator_tag(),
|
||||
category());
|
||||
BOOST_STATIC_ASSERT((boost::is_convertible<category, std::forward_iterator_tag>::value));
|
||||
}
|
||||
template <class IC> inline
|
||||
void Assert_bidirectional_category( const IC &/*ic*/) {
|
||||
typedef typename std::iterator_traits<IC>::iterator_category category;
|
||||
Assert_compile_time_tag( std::bidirectional_iterator_tag(),
|
||||
category());
|
||||
BOOST_STATIC_ASSERT((boost::is_convertible<category, std::bidirectional_iterator_tag>::value));
|
||||
}
|
||||
template <class IC> inline
|
||||
void Assert_random_access_category( const IC &/*ic*/) {
|
||||
typedef typename std::iterator_traits<IC>::iterator_category category;
|
||||
Assert_compile_time_tag( std::random_access_iterator_tag(),
|
||||
category());
|
||||
BOOST_STATIC_ASSERT((boost::is_convertible<category, std::random_access_iterator_tag>::value));
|
||||
}
|
||||
|
||||
// The assert at-least-category functions use the following
|
||||
// functions to resolve properly. Note the proper order of the
|
||||
// arguments: 1st is the to be type, 2nd is the actual type.
|
||||
|
|
@ -704,35 +698,32 @@ typedef Iterator_from_circulator< C, const_reference, const_pointer>
|
|||
: const_iterator( &anchor, 1);
|
||||
}
|
||||
};
|
||||
template < class Ctnr>
|
||||
template <class Container>
|
||||
class Circulator_from_container {
|
||||
typedef Circulator_from_container<Container> Self;
|
||||
typedef typename Container::iterator iterator;
|
||||
typedef std::iterator_traits<iterator> iterator_traits;
|
||||
public:
|
||||
// TYPES
|
||||
typedef typename iterator_traits::value_type value_type;
|
||||
typedef typename iterator_traits::reference reference;
|
||||
typedef typename iterator_traits::pointer pointer;
|
||||
typedef typename iterator_traits::difference_type difference_type;
|
||||
|
||||
typedef Circulator_from_container<Ctnr> Self;
|
||||
typedef Ctnr Container;
|
||||
typedef typename Ctnr::iterator iterator;
|
||||
typedef typename Ctnr::value_type value_type;
|
||||
typedef typename Ctnr::reference reference;
|
||||
typedef value_type* pointer;
|
||||
typedef typename Ctnr::size_type size_type;
|
||||
typedef typename Ctnr::difference_type difference_type;
|
||||
|
||||
typedef std::iterator_traits<iterator> ITraits;
|
||||
typedef typename ITraits::iterator_category Icategory;
|
||||
typedef I_Circulator_from_iterator_traits<Icategory> CTraits;
|
||||
typedef typename CTraits::iterator_category iterator_category;
|
||||
typedef typename I_Circulator_from_iterator_traits<
|
||||
typename iterator_traits::iterator_category
|
||||
>::iterator_category iterator_category;
|
||||
|
||||
typedef typename Container::size_type size_type;
|
||||
private:
|
||||
Ctnr* ctnr;
|
||||
Container* ctnr;
|
||||
iterator i;
|
||||
|
||||
public:
|
||||
// CREATION
|
||||
|
||||
Circulator_from_container() : ctnr(NULL) {}
|
||||
Circulator_from_container( Ctnr* c) : ctnr(c), i(c->begin()) {}
|
||||
Circulator_from_container( Ctnr* c, iterator j) : ctnr(c), i(j) {}
|
||||
Circulator_from_container( Container* c) : ctnr(c), i(c->begin()) {}
|
||||
Circulator_from_container( Container* c, iterator j) : ctnr(c), i(j) {}
|
||||
|
||||
// Gnu-bug workaround: define operator= explicitly.
|
||||
Self& operator=( const Self& c) {
|
||||
|
|
@ -790,8 +781,8 @@ public:
|
|||
Self& operator+=( difference_type n) {
|
||||
CGAL_assertion( ctnr != NULL);
|
||||
CGAL_assertion( i != ctnr->end());
|
||||
typename Ctnr::difference_type j = i - ctnr->begin();
|
||||
typename Ctnr::difference_type size = ctnr->size();
|
||||
typename Container::difference_type j = i - ctnr->begin();
|
||||
typename Container::difference_type size = ctnr->size();
|
||||
CGAL_assertion( j >= 0);
|
||||
CGAL_assertion( size >= 0);
|
||||
j = non_negative_mod( j + n, size);
|
||||
|
|
@ -821,7 +812,7 @@ public:
|
|||
}
|
||||
iterator current_iterator() const { return i;}
|
||||
Self min_circulator() const { return Self(ctnr); }
|
||||
Ctnr* container() const { return ctnr; }
|
||||
Container* container() const { return ctnr; }
|
||||
};
|
||||
|
||||
template <class Ctnr>
|
||||
|
|
|
|||
|
|
@ -33,54 +33,53 @@ namespace CGAL {
|
|||
struct Circulator_tag {}; // any circulator.
|
||||
struct Iterator_tag {}; // any iterator.
|
||||
|
||||
// conversion operators instead of inheritance to avoid ambiguous
|
||||
// bases. we have to repeat all possible conversion so we don't run
|
||||
// into a multiple user-defined conversions, problem.
|
||||
|
||||
struct Forward_circulator_tag
|
||||
: public std::forward_iterator_tag {};
|
||||
: public std::forward_iterator_tag
|
||||
{};
|
||||
|
||||
struct Bidirectional_circulator_tag
|
||||
: public std::bidirectional_iterator_tag {};
|
||||
: public std::bidirectional_iterator_tag
|
||||
{
|
||||
operator Forward_circulator_tag() const {}
|
||||
};
|
||||
|
||||
struct Random_access_circulator_tag
|
||||
: public std::random_access_iterator_tag {};
|
||||
template <class T, class Dist = std::ptrdiff_t, class Size = std::size_t>
|
||||
struct Forward_circulator_base {
|
||||
typedef T value_type;
|
||||
typedef Dist difference_type;
|
||||
typedef Size size_type;
|
||||
typedef T* pointer;
|
||||
typedef T& reference;
|
||||
typedef Forward_circulator_tag iterator_category;
|
||||
: public std::random_access_iterator_tag
|
||||
{
|
||||
operator Bidirectional_circulator_tag() const {}
|
||||
operator Forward_circulator_tag() const {}
|
||||
};
|
||||
template <class T, class Dist = std::ptrdiff_t, class Size = std::size_t>
|
||||
struct Bidirectional_circulator_base {
|
||||
typedef T value_type;
|
||||
typedef Dist difference_type;
|
||||
typedef Size size_type;
|
||||
typedef T* pointer;
|
||||
typedef T& reference;
|
||||
typedef Bidirectional_circulator_tag iterator_category;
|
||||
};
|
||||
template <class T, class Dist = std::ptrdiff_t, class Size = std::size_t>
|
||||
struct Random_access_circulator_base {
|
||||
typedef T value_type;
|
||||
typedef Dist difference_type;
|
||||
typedef Size size_type;
|
||||
typedef T* pointer;
|
||||
typedef T& reference;
|
||||
typedef Random_access_circulator_tag iterator_category;
|
||||
};
|
||||
template < class Category,
|
||||
class T,
|
||||
class Distance = std::ptrdiff_t,
|
||||
class Size = std::size_t,
|
||||
class Pointer = T*,
|
||||
class Reference = T&>
|
||||
|
||||
template <typename Tag, typename T, typename Distance = std::ptrdiff_t,
|
||||
/* size is so awkwardly placed to faciliate using the
|
||||
* default arguments from the derived classes */
|
||||
typename Size = std::size_t, typename Pointer = T*,
|
||||
typename Reference = T&>
|
||||
struct Circulator_base {
|
||||
typedef Category iterator_category;
|
||||
typedef T value_type;
|
||||
typedef Distance difference_type;
|
||||
typedef Size size_type;
|
||||
typedef Pointer pointer;
|
||||
typedef Reference reference;
|
||||
typedef Tag iterator_category;
|
||||
typedef T value_type;
|
||||
typedef Distance difference_type;
|
||||
typedef Pointer pointer;
|
||||
typedef Reference reference;
|
||||
typedef Size size_type;
|
||||
};
|
||||
|
||||
template <class T, class Dist = std::ptrdiff_t, class Size = std::size_t>
|
||||
struct Forward_circulator_base
|
||||
: Circulator_base<Forward_circulator_tag, T, Dist, Size> {};
|
||||
|
||||
template <class T, class Dist = std::ptrdiff_t, class Size = std::size_t>
|
||||
struct Bidirectional_circulator_base
|
||||
: Circulator_base<Bidirectional_circulator_tag, T, Dist, Size> {};
|
||||
|
||||
template <class T, class Dist = std::ptrdiff_t, class Size = std::size_t>
|
||||
struct Random_access_circulator_base
|
||||
: Circulator_base<Random_access_circulator_tag, T, Dist, Size> {};
|
||||
|
||||
// variant base classes
|
||||
// ---------------------
|
||||
template <class T, class Dist = std::ptrdiff_t, class Size = std::size_t>
|
||||
|
|
|
|||
|
|
@ -12,21 +12,16 @@ int main()
|
|||
typedef CGAL::Circulator_from_container< std::vector<int> > Circulator_from_vec;
|
||||
typedef CGAL::Circulator_from_container< std::list<int> > Circulator_from_list;
|
||||
|
||||
// neither of the container adaptors passes the checks for tag
|
||||
// convertibility
|
||||
|
||||
// BOOST_CONCEPT_ASSERT((CGAL::Concepts::RandomAccessCirculator<Circulator_from_vec>));
|
||||
// BOOST_CONCEPT_ASSERT((CGAL::Concepts::BidirectionalCirculator<Circulator_from_list>));
|
||||
BOOST_CONCEPT_ASSERT((CGAL::Concepts::RandomAccessCirculator<Circulator_from_vec>));
|
||||
BOOST_CONCEPT_ASSERT((CGAL::Concepts::BidirectionalCirculator<Circulator_from_list>));
|
||||
|
||||
typedef CGAL::Circulator_from_iterator<int*> Circulator_from_intp;
|
||||
typedef CGAL::Circulator_from_iterator<std::vector<int>::iterator> Circulator_from_veci;
|
||||
typedef CGAL::Circulator_from_iterator<std::list<int>::iterator> Circulator_from_listi;
|
||||
|
||||
// same as above
|
||||
// BOOST_CONCEPT_ASSERT((CGAL::Concepts::RandomAccessCirculator<Circulator_from_intp>));
|
||||
// BOOST_CONCEPT_ASSERT((CGAL::Concepts::RandomAccessCirculator<Circulator_from_veci>));
|
||||
// BOOST_CONCEPT_ASSERT((CGAL::Concepts::BidirectionalCirculator<Circulator_from_listi>));
|
||||
|
||||
BOOST_CONCEPT_ASSERT((CGAL::Concepts::RandomAccessCirculator<Circulator_from_intp>));
|
||||
BOOST_CONCEPT_ASSERT((CGAL::Concepts::RandomAccessCirculator<Circulator_from_veci>));
|
||||
BOOST_CONCEPT_ASSERT((CGAL::Concepts::BidirectionalCirculator<Circulator_from_listi>));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue