Class

CGAL::Circulator_tag

Definition

Iterators and circulators as well as different categories of circulators can be distinguished with the use of discriminating functions and the following circulator tags. A couple of base classes simplify the task of writing own circulators. They declare the appropriate tags and the local types needed for circulators. To use the tags or base classes only it is sufficient to include:

#include <CGAL/circulator_bases.h>


#include <CGAL/circulator.h>

Compile Time Tags

struct Circulator_tag;
any circulator.

struct Iterator_tag;
any iterator.


struct Forward_circulator_tag;
derived from forward_iterator_tag.

struct Bidirectional_circulator_tag;
derived from bidirectional_iterator_tag.

struct Random_access_circulator_tag;
derived from random_access_iterator_tag.

Base Classes

template < class Category, class T, class Dist = std::ptrdiff_t, class Size = std::size_t, class Ptr = T*, class Ref = T& >
struct Circulator_base;

template <class T, class Dist, class Size>
struct Forward_circulator_base;
template <class T, class Dist, class Size>
struct Bidirectional_circulator_base;
template <class T, class Dist, class Size>
struct Random_access_circulator_base;

See Also

query_circulator_or_iterator, Circulator_traits, Assert_circulator,
CGAL_For_all, is_empty_range, Circulator.

Example

The above declarations can be used to distinguish between iterators and circulators and between different circulator categories. The assertions can be used to protect a templatized algorithm against instantiations that do not fulfill the requirements. The following example program illustrates both.

File: examples/Circulator/circulator_prog3.cpp
#include <cassert>
#include <list>
#include <CGAL/circulator.h>

template <class C> inline  int foo( C c, std::forward_iterator_tag) {
    CGAL::Assert_circulator( c);
    CGAL::Assert_forward_category( c);
    return 1;
}
template <class C> inline  int foo( C c, std::random_access_iterator_tag) {
    CGAL::Assert_circulator( c);
    CGAL::Assert_random_access_category( c);
    return 2;
}
template <class I> inline  int foo( I i, CGAL::Iterator_tag) {
    CGAL::Assert_iterator( i);
    return 3;
}

template <class C> inline  int foo( C c, CGAL::Circulator_tag) {
    CGAL::Assert_circulator( c);
    typedef std::iterator_traits<C> Traits;
    typedef typename Traits::iterator_category iterator_category;
    return foo( c, iterator_category());
}
template <class IC> inline  int foo( IC ic) {
    typedef CGAL::Circulator_traits<IC> Traits;
    typedef typename Traits::category category;
    return foo( ic, category());
}

int main() {
    typedef CGAL::Forward_circulator_base<int>       F;
    typedef CGAL::Random_access_circulator_base<int> R;
    F f = F();
    R r = R();
    std::list<int> l;
    assert( foo( f)         == 1);
    assert( foo( r)         == 2);
    assert( foo( l.begin()) == 3);
    return 0;
}

Implementation

Since not all current compilers can eliminate the space needed for the compile time tags even when deriving from them, we implement a variant for each base class that contains a protected void* data member called _ptr. Here, the allocated space in the derived classes can be reused.

template <class T, class Dist, class Size>
class Forward_circulator_ptrbase;
forward circulator.

template <class T, class Dist, class Size>
class Bidirectional_circulator_ptrbase;
bidirectional circulator.

template <class T, class Dist, class Size>
class Random_access_circulator_ptrbase;
random access circulator.