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
|
#define CGAL_CIRCULATOR_H
|
||||||
|
|
||||||
#include <CGAL/basic.h>
|
#include <CGAL/basic.h>
|
||||||
|
#include <CGAL/circulator_bases.h>
|
||||||
|
#include <CGAL/use.h>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iterator>
|
#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
|
// These are name redefinitions for backwards compatibility
|
||||||
// with the pre iterator-traits style adaptors.
|
// with the pre iterator-traits style adaptors.
|
||||||
|
|
@ -73,25 +77,27 @@
|
||||||
|
|
||||||
namespace CGAL {
|
namespace CGAL {
|
||||||
|
|
||||||
template <class C>
|
namespace internal {
|
||||||
struct I_Circulator_traits {
|
|
||||||
typedef Iterator_tag category;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
// default to Iterator_tag, special case Circulator tags
|
||||||
struct I_Circulator_traits<Forward_circulator_tag> {
|
template<typename Tag>
|
||||||
typedef Circulator_tag category;
|
struct Get_category
|
||||||
};
|
{ typedef Iterator_tag type; };
|
||||||
|
|
||||||
template <>
|
template<>
|
||||||
struct I_Circulator_traits<Bidirectional_circulator_tag> {
|
struct Get_category<CGAL::Forward_circulator_tag>
|
||||||
typedef Circulator_tag category;
|
{ 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
|
// Circulator_size_traits are used by general adaptors for
|
||||||
// iterators and circulators. For example the N_step_adaptor
|
// 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>
|
template <class C>
|
||||||
struct Circulator_traits {
|
struct Circulator_traits {
|
||||||
typedef std::iterator_traits<C> traits;
|
private:
|
||||||
typedef typename traits::iterator_category ICAT;
|
typedef std::iterator_traits<C> iterator_traits;
|
||||||
typedef I_Circulator_traits<ICAT> C_traits;
|
public:
|
||||||
typedef typename C_traits::category category;
|
// 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 iterator_traits::value_type value_type;
|
||||||
typedef typename Ic_traits::iterator_category iterator_category;
|
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 I_Circulator_size_traits<
|
||||||
typedef typename Ci_traits::iterator_category circulator_category;
|
category, C>::size_type size_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class C>
|
template <class C>
|
||||||
|
|
@ -181,64 +195,44 @@ query_circulator_or_iterator( const C&) {
|
||||||
typedef typename Circulator_traits<C>::category category;
|
typedef typename Circulator_traits<C>::category category;
|
||||||
return 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
|
template <class C> inline
|
||||||
void Assert_circulator( const C &) {
|
void Assert_circulator( const C &) {
|
||||||
typedef typename Circulator_traits<C>::category category;
|
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
|
template <class I> inline
|
||||||
void Assert_iterator( const I &) {
|
void Assert_iterator( const I &) {
|
||||||
typedef typename Circulator_traits<I>::category category;
|
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
|
template <class I> inline
|
||||||
void Assert_input_category( const I &/*i*/) {
|
void Assert_input_category( const I &/*i*/) {
|
||||||
typedef typename std::iterator_traits<I>::iterator_category category;
|
typedef typename std::iterator_traits<I>::iterator_category category;
|
||||||
Assert_compile_time_tag( std::input_iterator_tag(),
|
BOOST_STATIC_ASSERT((boost::is_convertible<category, std::input_iterator_tag>::value));
|
||||||
category());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class I> inline
|
template <class I> inline
|
||||||
void Assert_output_category( const I &/*i*/) {
|
void Assert_output_category( const I &/*i*/) {
|
||||||
typedef typename std::iterator_traits<I>::iterator_category category;
|
typedef typename std::iterator_traits<I>::iterator_category category;
|
||||||
Assert_compile_time_tag( std::output_iterator_tag(),
|
BOOST_STATIC_ASSERT((boost::is_convertible<category, std::output_iterator_tag>::value));
|
||||||
category());
|
|
||||||
}
|
}
|
||||||
template <class IC> inline
|
template <class IC> inline
|
||||||
void Assert_forward_category( const IC &/*ic*/) {
|
void Assert_forward_category( const IC &/*ic*/) {
|
||||||
typedef typename std::iterator_traits<IC>::iterator_category category;
|
typedef typename std::iterator_traits<IC>::iterator_category category;
|
||||||
Assert_compile_time_tag( std::forward_iterator_tag(),
|
BOOST_STATIC_ASSERT((boost::is_convertible<category, std::forward_iterator_tag>::value));
|
||||||
category());
|
|
||||||
}
|
}
|
||||||
template <class IC> inline
|
template <class IC> inline
|
||||||
void Assert_bidirectional_category( const IC &/*ic*/) {
|
void Assert_bidirectional_category( const IC &/*ic*/) {
|
||||||
typedef typename std::iterator_traits<IC>::iterator_category category;
|
typedef typename std::iterator_traits<IC>::iterator_category category;
|
||||||
Assert_compile_time_tag( std::bidirectional_iterator_tag(),
|
BOOST_STATIC_ASSERT((boost::is_convertible<category, std::bidirectional_iterator_tag>::value));
|
||||||
category());
|
|
||||||
}
|
}
|
||||||
template <class IC> inline
|
template <class IC> inline
|
||||||
void Assert_random_access_category( const IC &/*ic*/) {
|
void Assert_random_access_category( const IC &/*ic*/) {
|
||||||
typedef typename std::iterator_traits<IC>::iterator_category category;
|
typedef typename std::iterator_traits<IC>::iterator_category category;
|
||||||
Assert_compile_time_tag( std::random_access_iterator_tag(),
|
BOOST_STATIC_ASSERT((boost::is_convertible<category, std::random_access_iterator_tag>::value));
|
||||||
category());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The assert at-least-category functions use the following
|
// The assert at-least-category functions use the following
|
||||||
// functions to resolve properly. Note the proper order of the
|
// functions to resolve properly. Note the proper order of the
|
||||||
// arguments: 1st is the to be type, 2nd is the actual type.
|
// 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);
|
: const_iterator( &anchor, 1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template < class Ctnr>
|
template <class Container>
|
||||||
class Circulator_from_container {
|
class Circulator_from_container {
|
||||||
|
typedef Circulator_from_container<Container> Self;
|
||||||
|
typedef typename Container::iterator iterator;
|
||||||
|
typedef std::iterator_traits<iterator> iterator_traits;
|
||||||
public:
|
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 typename I_Circulator_from_iterator_traits<
|
||||||
typedef Ctnr Container;
|
typename iterator_traits::iterator_category
|
||||||
typedef typename Ctnr::iterator iterator;
|
>::iterator_category iterator_category;
|
||||||
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 Container::size_type size_type;
|
||||||
private:
|
private:
|
||||||
Ctnr* ctnr;
|
Container* ctnr;
|
||||||
iterator i;
|
iterator i;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CREATION
|
// CREATION
|
||||||
|
|
||||||
Circulator_from_container() : ctnr(NULL) {}
|
Circulator_from_container() : ctnr(NULL) {}
|
||||||
Circulator_from_container( Ctnr* c) : ctnr(c), i(c->begin()) {}
|
Circulator_from_container( Container* c) : ctnr(c), i(c->begin()) {}
|
||||||
Circulator_from_container( Ctnr* c, iterator j) : ctnr(c), i(j) {}
|
Circulator_from_container( Container* c, iterator j) : ctnr(c), i(j) {}
|
||||||
|
|
||||||
// Gnu-bug workaround: define operator= explicitly.
|
// Gnu-bug workaround: define operator= explicitly.
|
||||||
Self& operator=( const Self& c) {
|
Self& operator=( const Self& c) {
|
||||||
|
|
@ -790,8 +781,8 @@ public:
|
||||||
Self& operator+=( difference_type n) {
|
Self& operator+=( difference_type n) {
|
||||||
CGAL_assertion( ctnr != NULL);
|
CGAL_assertion( ctnr != NULL);
|
||||||
CGAL_assertion( i != ctnr->end());
|
CGAL_assertion( i != ctnr->end());
|
||||||
typename Ctnr::difference_type j = i - ctnr->begin();
|
typename Container::difference_type j = i - ctnr->begin();
|
||||||
typename Ctnr::difference_type size = ctnr->size();
|
typename Container::difference_type size = ctnr->size();
|
||||||
CGAL_assertion( j >= 0);
|
CGAL_assertion( j >= 0);
|
||||||
CGAL_assertion( size >= 0);
|
CGAL_assertion( size >= 0);
|
||||||
j = non_negative_mod( j + n, size);
|
j = non_negative_mod( j + n, size);
|
||||||
|
|
@ -821,7 +812,7 @@ public:
|
||||||
}
|
}
|
||||||
iterator current_iterator() const { return i;}
|
iterator current_iterator() const { return i;}
|
||||||
Self min_circulator() const { return Self(ctnr); }
|
Self min_circulator() const { return Self(ctnr); }
|
||||||
Ctnr* container() const { return ctnr; }
|
Container* container() const { return ctnr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Ctnr>
|
template <class Ctnr>
|
||||||
|
|
|
||||||
|
|
@ -33,54 +33,53 @@ namespace CGAL {
|
||||||
struct Circulator_tag {}; // any circulator.
|
struct Circulator_tag {}; // any circulator.
|
||||||
struct Iterator_tag {}; // any iterator.
|
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
|
struct Forward_circulator_tag
|
||||||
: public std::forward_iterator_tag {};
|
: public std::forward_iterator_tag
|
||||||
|
{};
|
||||||
|
|
||||||
struct Bidirectional_circulator_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
|
struct Random_access_circulator_tag
|
||||||
: public std::random_access_iterator_tag {};
|
: public std::random_access_iterator_tag
|
||||||
template <class T, class Dist = std::ptrdiff_t, class Size = std::size_t>
|
{
|
||||||
struct Forward_circulator_base {
|
operator Bidirectional_circulator_tag() const {}
|
||||||
typedef T value_type;
|
operator Forward_circulator_tag() const {}
|
||||||
typedef Dist difference_type;
|
|
||||||
typedef Size size_type;
|
|
||||||
typedef T* pointer;
|
|
||||||
typedef T& reference;
|
|
||||||
typedef Forward_circulator_tag iterator_category;
|
|
||||||
};
|
};
|
||||||
template <class T, class Dist = std::ptrdiff_t, class Size = std::size_t>
|
|
||||||
struct Bidirectional_circulator_base {
|
template <typename Tag, typename T, typename Distance = std::ptrdiff_t,
|
||||||
typedef T value_type;
|
/* size is so awkwardly placed to faciliate using the
|
||||||
typedef Dist difference_type;
|
* default arguments from the derived classes */
|
||||||
typedef Size size_type;
|
typename Size = std::size_t, typename Pointer = T*,
|
||||||
typedef T* pointer;
|
typename Reference = T&>
|
||||||
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&>
|
|
||||||
struct Circulator_base {
|
struct Circulator_base {
|
||||||
typedef Category iterator_category;
|
typedef Tag iterator_category;
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
typedef Distance difference_type;
|
typedef Distance difference_type;
|
||||||
typedef Size size_type;
|
typedef Pointer pointer;
|
||||||
typedef Pointer pointer;
|
typedef Reference reference;
|
||||||
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
|
// variant base classes
|
||||||
// ---------------------
|
// ---------------------
|
||||||
template <class T, class Dist = std::ptrdiff_t, class Size = std::size_t>
|
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::vector<int> > Circulator_from_vec;
|
||||||
typedef CGAL::Circulator_from_container< std::list<int> > Circulator_from_list;
|
typedef CGAL::Circulator_from_container< std::list<int> > Circulator_from_list;
|
||||||
|
|
||||||
// neither of the container adaptors passes the checks for tag
|
BOOST_CONCEPT_ASSERT((CGAL::Concepts::RandomAccessCirculator<Circulator_from_vec>));
|
||||||
// convertibility
|
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<int*> Circulator_from_intp;
|
||||||
typedef CGAL::Circulator_from_iterator<std::vector<int>::iterator> Circulator_from_veci;
|
typedef CGAL::Circulator_from_iterator<std::vector<int>::iterator> Circulator_from_veci;
|
||||||
typedef CGAL::Circulator_from_iterator<std::list<int>::iterator> Circulator_from_listi;
|
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_intp>));
|
BOOST_CONCEPT_ASSERT((CGAL::Concepts::RandomAccessCirculator<Circulator_from_veci>));
|
||||||
// BOOST_CONCEPT_ASSERT((CGAL::Concepts::RandomAccessCirculator<Circulator_from_veci>));
|
BOOST_CONCEPT_ASSERT((CGAL::Concepts::BidirectionalCirculator<Circulator_from_listi>));
|
||||||
// BOOST_CONCEPT_ASSERT((CGAL::Concepts::BidirectionalCirculator<Circulator_from_listi>));
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue