From e623040728a60fc5d9fbf9bd41a9e3ac158e8c6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20M=C3=B6ller?= Date: Sat, 17 Nov 2012 02:05:19 +0100 Subject: [PATCH] Refactor circulators a little Give a name proper name to meta-functions that are not used outside Circulator and enable conversion between circulator tags. --- Circulator/include/CGAL/circulator.h | 143 ++++++++---------- Circulator/include/CGAL/circulator_bases.h | 81 +++++----- .../Circulator/circulator_concept_checks.cpp | 15 +- 3 files changed, 112 insertions(+), 127 deletions(-) diff --git a/Circulator/include/CGAL/circulator.h b/Circulator/include/CGAL/circulator.h index 9efc045bc9c..484a0c0d1dd 100644 --- a/Circulator/include/CGAL/circulator.h +++ b/Circulator/include/CGAL/circulator.h @@ -26,11 +26,15 @@ #define CGAL_CIRCULATOR_H #include +#include +#include + #include #include #include -#include -#include + +#include +#include // These are name redefinitions for backwards compatibility // with the pre iterator-traits style adaptors. @@ -73,25 +77,27 @@ namespace CGAL { -template -struct I_Circulator_traits { - typedef Iterator_tag category; -}; +namespace internal { -template <> -struct I_Circulator_traits { - typedef Circulator_tag category; -}; +// default to Iterator_tag, special case Circulator tags +template +struct Get_category +{ typedef Iterator_tag type; }; -template <> -struct I_Circulator_traits { - typedef Circulator_tag category; -}; +template<> +struct Get_category +{ typedef Circulator_tag type; }; + +template<> +struct Get_category +{ typedef Circulator_tag type; }; + +template<> +struct Get_category +{ typedef Circulator_tag type; }; + +} // internal -template <> -struct I_Circulator_traits { - 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 { template struct Circulator_traits { - typedef std::iterator_traits traits; - typedef typename traits::iterator_category ICAT; - typedef I_Circulator_traits C_traits; - typedef typename C_traits::category category; +private: + typedef std::iterator_traits 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 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 Ci_traits; - typedef typename Ci_traits::iterator_category circulator_category; + typedef typename I_Circulator_size_traits< + category, C>::size_type size_type; }; template @@ -181,64 +195,44 @@ query_circulator_or_iterator( const C&) { typedef typename Circulator_traits::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 -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 x; - x.match_compile_time_tag(b); -} -#endif template inline void Assert_circulator( const C &) { typedef typename Circulator_traits::category category; - Assert_compile_time_tag( Circulator_tag(), category()); + BOOST_STATIC_ASSERT((boost::is_convertible::value)); } + template inline void Assert_iterator( const I &) { typedef typename Circulator_traits::category category; - Assert_compile_time_tag( Iterator_tag(), category()); + BOOST_STATIC_ASSERT((boost::is_convertible::value)); } template inline void Assert_input_category( const I &/*i*/) { typedef typename std::iterator_traits::iterator_category category; - Assert_compile_time_tag( std::input_iterator_tag(), - category()); + BOOST_STATIC_ASSERT((boost::is_convertible::value)); } template inline void Assert_output_category( const I &/*i*/) { typedef typename std::iterator_traits::iterator_category category; - Assert_compile_time_tag( std::output_iterator_tag(), - category()); + BOOST_STATIC_ASSERT((boost::is_convertible::value)); } template inline void Assert_forward_category( const IC &/*ic*/) { typedef typename std::iterator_traits::iterator_category category; - Assert_compile_time_tag( std::forward_iterator_tag(), - category()); + BOOST_STATIC_ASSERT((boost::is_convertible::value)); } template inline void Assert_bidirectional_category( const IC &/*ic*/) { typedef typename std::iterator_traits::iterator_category category; - Assert_compile_time_tag( std::bidirectional_iterator_tag(), - category()); + BOOST_STATIC_ASSERT((boost::is_convertible::value)); } template inline void Assert_random_access_category( const IC &/*ic*/) { typedef typename std::iterator_traits::iterator_category category; - Assert_compile_time_tag( std::random_access_iterator_tag(), - category()); + BOOST_STATIC_ASSERT((boost::is_convertible::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 Circulator_from_container { + typedef Circulator_from_container Self; + typedef typename Container::iterator iterator; + typedef std::iterator_traits iterator_traits; public: -// TYPES - - typedef Circulator_from_container 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 ITraits; - typedef typename ITraits::iterator_category Icategory; - typedef I_Circulator_from_iterator_traits CTraits; - typedef typename CTraits::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 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 diff --git a/Circulator/include/CGAL/circulator_bases.h b/Circulator/include/CGAL/circulator_bases.h index 295a3591d4e..2f217fd0ede 100644 --- a/Circulator/include/CGAL/circulator_bases.h +++ b/Circulator/include/CGAL/circulator_bases.h @@ -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 -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 -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 -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 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 +struct Forward_circulator_base + : Circulator_base {}; + +template +struct Bidirectional_circulator_base + : Circulator_base {}; + +template +struct Random_access_circulator_base + : Circulator_base {}; + // variant base classes // --------------------- template diff --git a/Circulator/test/Circulator/circulator_concept_checks.cpp b/Circulator/test/Circulator/circulator_concept_checks.cpp index 69615405e5b..0c204dca385 100644 --- a/Circulator/test/Circulator/circulator_concept_checks.cpp +++ b/Circulator/test/Circulator/circulator_concept_checks.cpp @@ -12,21 +12,16 @@ int main() typedef CGAL::Circulator_from_container< std::vector > Circulator_from_vec; typedef CGAL::Circulator_from_container< std::list > Circulator_from_list; - // neither of the container adaptors passes the checks for tag - // convertibility - - // BOOST_CONCEPT_ASSERT((CGAL::Concepts::RandomAccessCirculator)); - // BOOST_CONCEPT_ASSERT((CGAL::Concepts::BidirectionalCirculator)); + BOOST_CONCEPT_ASSERT((CGAL::Concepts::RandomAccessCirculator)); + BOOST_CONCEPT_ASSERT((CGAL::Concepts::BidirectionalCirculator)); typedef CGAL::Circulator_from_iterator Circulator_from_intp; typedef CGAL::Circulator_from_iterator::iterator> Circulator_from_veci; typedef CGAL::Circulator_from_iterator::iterator> Circulator_from_listi; - - // same as above - // BOOST_CONCEPT_ASSERT((CGAL::Concepts::RandomAccessCirculator)); - // BOOST_CONCEPT_ASSERT((CGAL::Concepts::RandomAccessCirculator)); - // BOOST_CONCEPT_ASSERT((CGAL::Concepts::BidirectionalCirculator)); + BOOST_CONCEPT_ASSERT((CGAL::Concepts::RandomAccessCirculator)); + BOOST_CONCEPT_ASSERT((CGAL::Concepts::RandomAccessCirculator)); + BOOST_CONCEPT_ASSERT((CGAL::Concepts::BidirectionalCirculator)); return 0; }