mirror of https://github.com/CGAL/cgal
683 lines
16 KiB
C++
683 lines
16 KiB
C++
namespace CGAL {
|
|
|
|
|
|
/*!
|
|
\addtogroup PkgHandlesAndCirculatorsAssert
|
|
|
|
Each of the following assertions, applicable to an iterator
|
|
or a circulator or both,
|
|
checks at compile time if its argument
|
|
is of the kind stated in the assertions name, i.e.\ a circulator, an
|
|
iterator, or a particular category of either an iterator or
|
|
a circulator. Note that neither input nor output circulators exists.
|
|
|
|
\sa `Circulator_tag`
|
|
\sa `Circulator_traits`
|
|
\sa `query_circulator_or_iterator`
|
|
\sa `Circulator`
|
|
|
|
*/
|
|
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculatorsAssert
|
|
|
|
checks at compile time if its argument is a circulator.
|
|
|
|
*/
|
|
template <class C>
|
|
void Assert_circulator( const C &c);
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculatorsAssert
|
|
|
|
checks at compile time if its argument is an iterator.
|
|
|
|
*/
|
|
template <class I>
|
|
void Assert_iterator( const I &i);
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculatorsAssert
|
|
|
|
checks at compile time if its argument is a circulator or iterator.
|
|
|
|
*/
|
|
template< class IC>
|
|
void Assert_circulator_or_iterator(const IC& i);
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculatorsAssert
|
|
|
|
*/
|
|
template <class I>
|
|
void Assert_input_category( const I &i);
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculatorsAssert
|
|
|
|
*/
|
|
template <class I>
|
|
void Assert_output_category( const I &i);
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculatorsAssert
|
|
|
|
*/
|
|
template <class IC>
|
|
void Assert_forward_category( const IC &ic);
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculatorsAssert
|
|
|
|
*/
|
|
template <class IC>
|
|
void Assert_bidirectional_category( const IC &ic);
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculatorsAssert
|
|
|
|
*/
|
|
template <class IC>
|
|
void Assert_random_access_category( const IC &ic);
|
|
|
|
} /* namespace CGAL */
|
|
|
|
namespace CGAL {
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculatorsFunctions
|
|
|
|
The distance of a circulator `c` to a circulator `d` is the number of
|
|
elements in the range `[c, d)`. It is defined to be zero
|
|
for a circulator on an empty sequence and it returns the size of the data
|
|
structure when applied to a range of the form `[c, c)`.
|
|
|
|
\sa `circulator_size`
|
|
\sa `iterator_distance`
|
|
\sa `is_empty_range`
|
|
\sa `Circulator`
|
|
|
|
*/
|
|
template <class C> C::difference_type
|
|
circulator_distance(C c, C d);
|
|
|
|
} /* namespace CGAL */
|
|
|
|
|
|
namespace CGAL {
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculatorsAdapter
|
|
|
|
The adaptor `Circulator_from_container` provides a circulator for an \stl container `C` of equal category as the iterator provided by the container.
|
|
The iterator must be at least of the forward iterator
|
|
category. The corresponding non-mutable circulator is called
|
|
`Const_circulator_from_container<C>`.
|
|
|
|
The container type `C` is supposed to conform to the \stl
|
|
requirements for container (i.e.\ to have a `begin()` and an
|
|
`end()` iterator as well as the local types
|
|
`reference`, `const_reference`, `value_type`,
|
|
`size_type`, and `difference_type`).
|
|
|
|
\cgalHeading{Types}
|
|
|
|
All types required for circulators are provided.
|
|
|
|
\cgalHeading{Operations}
|
|
|
|
The adaptor conforms to the requirements of the corresponding
|
|
circulator category. An additional member function
|
|
`current_iterator()` returns the current iterator pointing to
|
|
the same position as the circulator does.
|
|
|
|
\sa `Container_from_circulator`
|
|
\sa `Circulator_from_iterator`
|
|
\sa `Circulator`
|
|
|
|
\cgalHeading{Example}
|
|
|
|
The following program composes two adaptors - from a container to a
|
|
circulator and back to an iterator. It applies an \stl sort algorithm
|
|
on a \stl vector with three elements. The resulting vector will be
|
|
<TT>[2 5 9]</TT> as it is checked by the assertions. The program is
|
|
part of the \cgal distribution.
|
|
|
|
\cgalExample{Circulator/circulator_prog2.cpp}
|
|
|
|
*/
|
|
template< typename C >
|
|
class Circulator_from_container {
|
|
public:
|
|
|
|
/// \name Creation
|
|
/// @{
|
|
|
|
/*!
|
|
a circulator `c` on an empty sequence.
|
|
*/
|
|
Circulator_from_container();
|
|
|
|
/*!
|
|
a circulator `c` initialized to refer to the first element in
|
|
`container`, i.e.\ `container.begin()`.
|
|
The circulator `c` refers to an empty sequence if the
|
|
`container` is empty.
|
|
|
|
*/
|
|
Circulator_from_container(C* container);
|
|
|
|
/*!
|
|
a circulator `c` initialized to refer to the element `*i` in
|
|
`container`. \pre `*i` is dereferenceable and refers to `container`.
|
|
|
|
*/
|
|
Circulator_from_container(C* container, C::iterator i);
|
|
|
|
/// @}
|
|
|
|
}; /* end Circulator_from_container */
|
|
} /* end namespace CGAL */
|
|
|
|
namespace CGAL {
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculatorsAdapter
|
|
|
|
The adaptor `Circulator_from_iterator` converts two iterators of type
|
|
`I`, a begin and a past-the-end value, to a circulator of equal
|
|
category. The iterator must be at least of the forward iterator
|
|
category. The circulator will be mutable or non-mutable according to
|
|
the iterator. Iterators provide no `size_type`. This adapter
|
|
assumes `std::size_t` instead.
|
|
|
|
\cgalHeading{Operations}
|
|
|
|
The adaptor conforms to the requirements of the respective circulator
|
|
category. An additional member function `current_iterator()`
|
|
returns the current iterator pointing to the same position as the
|
|
circulator does.
|
|
|
|
\sa `Container_from_circulator`
|
|
\sa `Circulator_from_container`
|
|
\sa `Circulator`
|
|
|
|
\cgalHeading{Example}
|
|
|
|
The following program composes two adaptors - from an iterator to a
|
|
circulator and back to an iterator. It applies an \stl sort algorithm
|
|
on a \stl vector containing three elements. The resulting vector will
|
|
be <TT>[2 5 9]</TT> as it is checked by the assertions. The program is
|
|
part of the \cgal distribution.
|
|
|
|
\cgalExample{Circulator/circulator_prog1.cpp}
|
|
|
|
Another example usage for this adaptor is a random access circulator
|
|
over the built-in C arrays. Given an array of type <TT>T*</TT> with a
|
|
begin pointer <TT>b</TT> and a past-the-end pointer <TT>e</TT> the adaptor
|
|
`Circulator_from_iterator<T*> c(b,e)` is a random access circulator
|
|
`c` over this array.
|
|
|
|
*/
|
|
template< typename I >
|
|
class Circulator_from_iterator {
|
|
public:
|
|
|
|
/// \name Types
|
|
/// In addition all types required for circulators are provided.
|
|
/// @{
|
|
|
|
/*!
|
|
|
|
*/
|
|
typedef I iterator;
|
|
|
|
/// @}
|
|
|
|
/// \name Creation
|
|
/// @{
|
|
|
|
/*!
|
|
a circulator `c` on an empty sequence.
|
|
*/
|
|
Circulator_from_iterator();
|
|
|
|
/*!
|
|
a circulator `c` initialized to refer to the element
|
|
`*cur` in a range `[begin, end)`.
|
|
The circulator `c` refers to a empty sequence
|
|
if `begin==end`.
|
|
|
|
*/
|
|
Circulator_from_iterator(const I& begin,
|
|
const I& end, const I& cur = begin);
|
|
|
|
/*!
|
|
a copy of circulator `d` referring to the element `*cur`.
|
|
The circulator `c` refers to a empty sequence
|
|
if `d` does so.
|
|
|
|
*/
|
|
Circulator_from_iterator(
|
|
const Circulator_from_iterator<I,T,Size,Dist>& d,
|
|
const I& cur);
|
|
|
|
/// @}
|
|
|
|
}; /* end Circulator_from_iterator */
|
|
} /* end namespace CGAL */
|
|
namespace CGAL {
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculatorsFunctions
|
|
|
|
The size of a circulator is the size of the data structure it refers
|
|
to. It is zero for a circulator on an empty sequence. The size can be
|
|
computed in linear time for forward and bidirectional circulators, and
|
|
in constant time for random access circulators using the minimal
|
|
circulator. The function `circulator_size(c)`
|
|
returns the circulator size. It uses the
|
|
`c.min_circulator()` function if `c` is a random
|
|
access circulator.
|
|
|
|
\sa `circulator_distance`
|
|
\sa `iterator_distance`
|
|
\sa `is_empty_range`
|
|
\sa `Circulator`
|
|
|
|
*/
|
|
template <class C> C::size_type circulator_size(C c);
|
|
|
|
} /* namespace CGAL */
|
|
|
|
|
|
namespace CGAL {
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculators
|
|
|
|
The circulator traits class distinguishes between circulators and
|
|
iterators. It defines a local type `category` that is identical to the
|
|
type `Circulator_tag` if the iterator category of the argument
|
|
`C` is a circulator category. Otherwise it is identical to the type
|
|
`Iterator_tag`.
|
|
|
|
The local type `iterator_category` gives the corresponding
|
|
iterator category for circulators, i.e.\ one of
|
|
`forward_iterator_tag`, `bidirectional_iterator_tag`, or
|
|
`random_access_iterator_tag`.
|
|
|
|
The local type `circulator_category` gives the corresponding
|
|
circulator category for iterators, i.e.\ one of
|
|
`Forward_circulator_tag`, `Bidirectional_circulator_tag`, or
|
|
`Random_access_circulator_tag`.
|
|
|
|
\cgalHeading{Example}
|
|
|
|
A generic function `bar` that distinguishes between a call with a
|
|
circulator range and a call with an iterator range:
|
|
|
|
\code{.cpp}
|
|
|
|
template <class I>
|
|
void bar( I i, I j, CGAL::Iterator_tag) {
|
|
CGAL::Assert_iterator(i);
|
|
// This function is called for iterator ranges [i,j).
|
|
}
|
|
|
|
template <class C>
|
|
void bar( C c, C d, CGAL::Circulator_tag) {
|
|
CGAL::Assert_circulator(c);
|
|
// This function is called for circulator ranges [c,d).
|
|
}
|
|
|
|
template <class IC>
|
|
void bar( IC i, IC j) { // calls the correct function
|
|
return bar( i, j, typename CGAL::Circulator_traits<IC>::category());
|
|
}
|
|
\endcode
|
|
|
|
*/
|
|
template< typename C >
|
|
class Circulator_traits {
|
|
public:
|
|
|
|
/// \name Types
|
|
/// @{
|
|
|
|
/*!
|
|
either `Iterator_tag` or
|
|
`Circulator_tag`.
|
|
*/
|
|
typedef Hidden_type category;
|
|
|
|
/*!
|
|
|
|
corresponding iterator category for circulators.
|
|
*/
|
|
typedef Hidden_type iterator_category;
|
|
|
|
/*!
|
|
|
|
corresponding circulator category for iterator.
|
|
*/
|
|
typedef Hidden_type circulator_category;
|
|
|
|
/// @}
|
|
|
|
}; /* end Circulator_traits */
|
|
} /* end namespace CGAL */
|
|
|
|
namespace CGAL {
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculatorsAdapter
|
|
|
|
The adaptor `Container_from_circulator` is a class that converts any
|
|
circulator type `C` to a kind of container class, i.e.\ a class
|
|
that provides an `iterator` and a `const_iterator`
|
|
type and two member functions - `begin()` and `end()`
|
|
- that return the appropriate iterators. By analogy to \stl container classes these member functions return a const iterator in
|
|
the case that the container itself is constant and a mutable iterator
|
|
otherwise.
|
|
|
|
\sa `Circulator_from_iterator`
|
|
\sa `Circulator_from_container`
|
|
\sa `Circulator`
|
|
|
|
\cgalHeading{Example}
|
|
|
|
The generic <TT>reverse()</TT> algorithm from the \stl can be used with an
|
|
adaptor if at least a bidirectional circulator <TT>c</TT> is given.
|
|
|
|
\code{.cpp}
|
|
|
|
Circulator c; // c is assumed to be a bidirectional circulator.
|
|
CGAL::Container_from_circulator<Circulator> container(c);
|
|
reverse( container.begin(), container.end());
|
|
|
|
\endcode
|
|
|
|
\cgalHeading{Implementation}
|
|
|
|
The iterator adaptor keeps track of the number of rounds a circulator
|
|
has done around the ring-like data structure (a kind of winding
|
|
number). It is used to distinguish between the start position and the
|
|
end position which will be denoted by the same circulator internally.
|
|
This winding number is zero for the `begin()`-iterator and one
|
|
for the `end()`-iterator. It is incremented whenever the
|
|
internal circulator passes the `begin()` position. Two
|
|
iterators are equal if their internally used circulators and winding
|
|
numbers are equal.
|
|
This is more general than necessary since an iterator equal to
|
|
`end()`-iterator is not supposed to be incremented
|
|
any more, which is here still possible in a defined manner.
|
|
|
|
The implementation is different for random access iterators.
|
|
The random access iterator has to be able to compute the size of the
|
|
data structure in constant time. This is for example needed if the
|
|
difference of the past-the-end iterator and the begin iterator is
|
|
taken, which is exactly the size of the data structure.
|
|
Therefore, if the circulator is of the random-access category, the
|
|
adapter chooses the minimal circulator for the internal anchor
|
|
position. The minimal circulator is part of the random access
|
|
circulator requirements, see
|
|
Page \ref sectionMinCircleRequ. For the random
|
|
access iterator the adaptor implements a total ordering relation that
|
|
is currently not required for random access circulators.
|
|
|
|
*/
|
|
template< typename C >
|
|
class Container_from_circulator {
|
|
public:
|
|
|
|
/// \name Types
|
|
/// @{
|
|
|
|
/*!
|
|
|
|
*/
|
|
typedef C Circulator;
|
|
|
|
/*!
|
|
|
|
*/
|
|
typedef Hidden_type iterator;
|
|
|
|
/*!
|
|
|
|
*/
|
|
typedef Hidden_type const_iterator;
|
|
|
|
/*!
|
|
|
|
*/
|
|
typedef Hidden_type value_type;
|
|
|
|
/*!
|
|
|
|
*/
|
|
typedef Hidden_type reference;
|
|
|
|
/*!
|
|
|
|
*/
|
|
typedef Hidden_type const_reference;
|
|
|
|
/*!
|
|
|
|
*/
|
|
typedef Hidden_type pointer;
|
|
|
|
/*!
|
|
|
|
*/
|
|
typedef Hidden_type const_pointer;
|
|
|
|
/*!
|
|
|
|
*/
|
|
typedef Hidden_type size_type;
|
|
|
|
/*!
|
|
|
|
*/
|
|
typedef Hidden_type difference_type;
|
|
|
|
/// @}
|
|
|
|
/// \name Creation
|
|
/// @{
|
|
|
|
/*!
|
|
any iterator of `container` will have a singular value.
|
|
*/
|
|
Container_from_circulator();
|
|
|
|
/*!
|
|
any iterator of `container` will have a singular value if the
|
|
circulator `c` corresponds to an empty sequence.
|
|
*/
|
|
Container_from_circulator(const C& c);
|
|
|
|
/// @}
|
|
|
|
/// \name Operations
|
|
/// The `iterator` and `const_iterator` types are of the appropriate
|
|
/// iterator category. In addition to the operations required for
|
|
/// their category, they have a member function `current_circulator()`
|
|
/// that returns a circulator pointing to the same position as the
|
|
/// iterator does.
|
|
/// @{
|
|
|
|
/*!
|
|
the start iterator.
|
|
*/
|
|
iterator begin();
|
|
|
|
/*!
|
|
the start const iterator.
|
|
*/
|
|
const_iterator begin() const;
|
|
|
|
/*!
|
|
the past-the-end iterator.
|
|
*/
|
|
iterator end();
|
|
|
|
/*!
|
|
the past-the-end const iterator.
|
|
*/
|
|
const_iterator end() const;
|
|
|
|
/// @}
|
|
|
|
}; /* end Container_from_circulator */
|
|
} /* end namespace CGAL */
|
|
namespace CGAL {
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculatorsFunctions
|
|
|
|
is `true` if the range `[i, j)` is empty, `false` otherwise.
|
|
|
|
In order to write algorithms that work with iterator ranges as well as
|
|
with circulator ranges we have to consider the difference of
|
|
representing an empty range. For iterators this is the range `[i,i)`,
|
|
while for circulators it would be `c == NULL`, the empty sequence test.
|
|
The function `is_empty_range` provides the necessary generic test
|
|
which accepts an iterator range or a circulator range and says whether
|
|
the range is empty or not.
|
|
|
|
\pre `IC` is either a circulator or an iterator type. The range `[i, j)` is valid.
|
|
|
|
\cgalHeading{Example}
|
|
|
|
The following function `process_all` accepts a range `[i, j)` of an iterator or circulator `IC` and processes each
|
|
element in this range:
|
|
|
|
\code{.cpp}
|
|
template <class IC>
|
|
void process_all( IC i, IC j) {
|
|
if (! CGAL::is_empty_range( i, j)) {
|
|
do {
|
|
process(*i);
|
|
} while (++i != j);
|
|
}
|
|
}
|
|
\endcode
|
|
|
|
\sa `iterator_distance`
|
|
\sa `CGAL_For_all`
|
|
\sa `Circulator_tag`
|
|
\sa `Circulator_traits`
|
|
\sa `Assert_circulator_or_iterator`
|
|
\sa `Circulator`
|
|
|
|
*/
|
|
template< class IC>
|
|
bool is_empty_range( const IC& i, const IC& j);
|
|
|
|
} /* namespace CGAL */
|
|
|
|
namespace CGAL {
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculatorsFunctions
|
|
|
|
The following function returns the distance between either two
|
|
iterators or two circulators.
|
|
|
|
\sa `circulator_size`
|
|
\sa `circulator_distance`
|
|
\sa `is_empty_range`
|
|
\sa `Circulator_tag`
|
|
\sa `Assert_circulator_or_iterator`
|
|
\sa `CGAL_For_all`
|
|
\sa `Circulator`
|
|
|
|
*/
|
|
template <class IC> iterator_traits<IC>::difference_type
|
|
iterator_distance(IC ic1, IC ic2);
|
|
|
|
} /* namespace CGAL */
|
|
|
|
namespace CGAL {
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculatorsFunctions
|
|
|
|
This function matches for type `I` if the iterator category of `I` belongs to an iterator.
|
|
|
|
\sa `Circulator_tag`
|
|
\sa `Circulator_traits`
|
|
\sa `Assert_circulator`
|
|
\sa `Circulator`
|
|
*/
|
|
template <class I>
|
|
Iterator_tag query_circulator_or_iterator( const I& i);
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculatorsFunctions
|
|
|
|
This functiona matches for type `C` if the iterator category of `C` belongs to a circulator.
|
|
|
|
\sa `Circulator_tag`
|
|
\sa `Circulator_traits`
|
|
\sa `Assert_circulator`
|
|
\sa `Circulator`
|
|
|
|
*/
|
|
template <class C>
|
|
Circulator_tag query_circulator_or_iterator( const C& c);
|
|
|
|
} /* namespace CGAL */
|
|
|
|
|
|
|
|
/*!
|
|
\ingroup PkgHandlesAndCirculatorsFunctions
|
|
|
|
In order to write algorithms that work with iterator ranges as well as
|
|
with circulator ranges we have to consider the difference of
|
|
representing an empty range. For iterators this is the range `[i,i)`,
|
|
while for circulators it would be `c == NULL`, the empty sequence test.
|
|
The function `is_empty_range` provides the necessary generic test
|
|
which accepts an iterator range or a circulator range and says whether
|
|
the range is empty or not.
|
|
|
|
A macro `CGAL_For_all( i, j)` simplifies the writing of such simple
|
|
loops as the one in the example of the function `is_empty_range`.
|
|
`i` and `j` can be either iterators or circulators. The macro
|
|
loops through the range `[i, j)`. It increments `i` until it
|
|
reaches `j`. The implementation looks like:
|
|
|
|
\code
|
|
for ( bool _circ_loop_flag = ! ::CGAL::is_empty_range(i,j);
|
|
_circ_loop_flag;
|
|
_circ_loop_flag = ((++i) != (j))
|
|
)
|
|
\endcode
|
|
|
|
|
|
Note that the macro behaves like a `for`-loop. It can be used with
|
|
a single statement or with a statement block. For bidirectional
|
|
iterators or circulators, a backwards loop macro
|
|
`CGAL_For_all_backwards(i, j)` exists that decrements `j` until
|
|
it reaches `i`.
|
|
|
|
\sa `CGAL::iterator_distance`
|
|
\sa `CGAL::is_empty_range`
|
|
\sa `CGAL::Circulator_tag`
|
|
\sa `CGAL::Circulator_traits`
|
|
\sa `CGAL::Assert_circulator_or_iterator`
|
|
\sa `Circulator`
|
|
|
|
*/
|
|
#define CGAL_For_all(i,j)
|
|
|
|
/// \ingroup PkgHandlesAndCirculatorsFunctions
|
|
/// See ::CGAL_For_all
|
|
#define CGAL_For_all_backwards(i,j)
|