forked from boostorg/iterator
This commit was manufactured by cvs2svn to create branch
'iterator_adaptor_update'. [SVN r11341]
This commit is contained in:
@ -1,159 +0,0 @@
|
|||||||
#ifndef BOOST_ITERATOR_CATEGORIES_HPP
|
|
||||||
#define BOOST_ITERATOR_CATEGORIES_HPP
|
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
#include <boost/type_traits/conversion_traits.hpp>
|
|
||||||
#include <boost/type_traits/cv_traits.hpp>
|
|
||||||
#include <boost/pending/ct_if.hpp>
|
|
||||||
#include <boost/detail/iterator.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
// Return Type Categories
|
|
||||||
struct readable_iterator_tag { };
|
|
||||||
struct writable_iterator_tag { };
|
|
||||||
struct swappable_iterator_tag { };
|
|
||||||
struct mutable_lvalue_iterator_tag :
|
|
||||||
virtual public writable_iterator_tag,
|
|
||||||
virtual public readable_iterator_tag { };
|
|
||||||
struct constant_lvalue_iterator_tag :
|
|
||||||
virtual public readable_iterator_tag { };
|
|
||||||
|
|
||||||
// Traversal Categories
|
|
||||||
struct forward_traversal_tag { };
|
|
||||||
struct bidirectional_traversal_tag : public forward_traversal_tag { };
|
|
||||||
struct random_access_traversal_tag : public bidirectional_traversal_tag { };
|
|
||||||
|
|
||||||
struct error_iterator_tag { };
|
|
||||||
|
|
||||||
// Inherit from iterator_base if your iterator defines its own
|
|
||||||
// return_category and traversal_category. Otherwise, the "old style"
|
|
||||||
// iterator category will be mapped to the return_category and
|
|
||||||
// traversal_category.
|
|
||||||
struct new_iterator_base { };
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
struct return_category_from_nested_type {
|
|
||||||
template <typename Iterator> struct bind {
|
|
||||||
typedef typename Iterator::return_category type;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct traversal_category_from_nested_type {
|
|
||||||
template <typename Iterator> struct bind {
|
|
||||||
typedef typename Iterator::traversal_category type;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ValueType>
|
|
||||||
struct choose_lvalue_return {
|
|
||||||
typedef typename ct_if<is_const<ValueType>::value,
|
|
||||||
boost::constant_lvalue_iterator_tag,
|
|
||||||
boost::mutable_lvalue_iterator_tag>::type type;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template <typename Category, typename ValueType>
|
|
||||||
struct iter_category_to_return {
|
|
||||||
typedef typename ct_if<
|
|
||||||
is_convertible<Category*, std::forward_iterator_tag*>::value,
|
|
||||||
typename choose_lvalue_return<ValueType>::type,
|
|
||||||
typename ct_if<
|
|
||||||
is_convertible<Category*, std::input_iterator_tag*>::value,
|
|
||||||
boost::readable_iterator_tag,
|
|
||||||
typename ct_if<
|
|
||||||
is_convertible<Category*, std::output_iterator_tag*>::value,
|
|
||||||
boost::writable_iterator_tag,
|
|
||||||
boost::error_iterator_tag
|
|
||||||
>::type
|
|
||||||
>::type
|
|
||||||
>::type type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Category>
|
|
||||||
struct iter_category_to_traversal {
|
|
||||||
typedef typename ct_if<
|
|
||||||
is_convertible<Category*, std::random_access_iterator_tag*>::value,
|
|
||||||
random_access_traversal_tag,
|
|
||||||
typename ct_if<
|
|
||||||
is_convertible<Category*, std::bidirectional_iterator_tag*>::value,
|
|
||||||
bidirectional_traversal_tag,
|
|
||||||
forward_traversal_tag
|
|
||||||
>::type
|
|
||||||
>::type type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct return_category_from_old_traits {
|
|
||||||
template <typename Iterator> class bind {
|
|
||||||
typedef boost::detail::iterator_traits<Iterator> OldTraits;
|
|
||||||
typedef typename OldTraits::iterator_category Cat;
|
|
||||||
typedef typename OldTraits::value_type value_type;
|
|
||||||
public:
|
|
||||||
typedef iter_category_to_return<Cat, value_type>::type type;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct traversal_category_from_old_traits {
|
|
||||||
template <typename Iterator> class bind {
|
|
||||||
typedef boost::detail::iterator_traits<Iterator> OldTraits;
|
|
||||||
typedef typename OldTraits::iterator_category Cat;
|
|
||||||
public:
|
|
||||||
typedef iter_category_to_traversal<Cat>::type type;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
class choose_return_category {
|
|
||||||
typedef typename ct_if<is_convertible<Iterator*,
|
|
||||||
new_iterator_base*>::value,
|
|
||||||
return_category_from_nested_type,
|
|
||||||
return_category_from_old_traits>::type Choice;
|
|
||||||
public:
|
|
||||||
typedef typename Choice:: template bind<Iterator>::type type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
class choose_traversal_category {
|
|
||||||
typedef typename ct_if<is_convertible<Iterator*,
|
|
||||||
new_iterator_base*>::value,
|
|
||||||
traversal_category_from_nested_type,
|
|
||||||
traversal_category_from_old_traits>::type Choice;
|
|
||||||
public:
|
|
||||||
typedef typename Choice:: template bind<Iterator>::type type;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template <class Iterator>
|
|
||||||
struct return_category {
|
|
||||||
typedef typename detail::choose_return_category<Iterator>::type type;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template <class Iterator>
|
|
||||||
struct traversal_category {
|
|
||||||
typedef typename detail::choose_traversal_category<Iterator>::type type;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct return_category<T*>
|
|
||||||
{
|
|
||||||
typedef typename ct_if<is_const<T>::value,
|
|
||||||
constant_lvalue_iterator_tag,
|
|
||||||
mutable_lvalue_iterator_tag>::type type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct traversal_category<T*>
|
|
||||||
{
|
|
||||||
typedef random_access_traversal_tag type;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#endif // BOOST_ITERATOR_CATEGORIES_HPP
|
|
@ -1,172 +0,0 @@
|
|||||||
#ifndef BOOST_ITERATOR_CONCEPTS_HPP
|
|
||||||
#define BOOST_ITERATOR_CONCEPTS_HPP
|
|
||||||
|
|
||||||
#include <boost/concept_check.hpp>
|
|
||||||
#include <boost/iterator_categories.hpp>
|
|
||||||
#include <boost/type_traits/conversion_traits.hpp>
|
|
||||||
#include <boost/static_assert.hpp>
|
|
||||||
|
|
||||||
namespace boost_concepts {
|
|
||||||
// Used a different namespace here (instead of "boost") so that the
|
|
||||||
// concept descriptions do not take for granted the names in
|
|
||||||
// namespace boost.
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
// Iterator Access Concepts
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
class ReadableIteratorConcept {
|
|
||||||
public:
|
|
||||||
typedef typename std::iterator_traits<Iterator>::value_type value_type;
|
|
||||||
typedef typename std::iterator_traits<Iterator>::reference reference;
|
|
||||||
typedef typename boost::return_category<Iterator>::type return_category;
|
|
||||||
|
|
||||||
void constraints() {
|
|
||||||
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
|
|
||||||
boost::function_requires< boost::EqualityComparableConcept<Iterator> >();
|
|
||||||
boost::function_requires<
|
|
||||||
boost::DefaultConstructibleConcept<Iterator> >();
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT((boost::is_convertible<return_category*,
|
|
||||||
boost::readable_iterator_tag*>::value));
|
|
||||||
|
|
||||||
reference r = *i; // or perhaps read(x)
|
|
||||||
value_type v(r);
|
|
||||||
boost::ignore_unused_variable_warning(v);
|
|
||||||
}
|
|
||||||
Iterator i;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Iterator, typename ValueType>
|
|
||||||
class WritableIteratorConcept {
|
|
||||||
public:
|
|
||||||
typedef typename boost::return_category<Iterator>::type return_category;
|
|
||||||
|
|
||||||
void constraints() {
|
|
||||||
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
|
|
||||||
boost::function_requires< boost::EqualityComparableConcept<Iterator> >();
|
|
||||||
boost::function_requires<
|
|
||||||
boost::DefaultConstructibleConcept<Iterator> >();
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT((boost::is_convertible<return_category*,
|
|
||||||
boost::writable_iterator_tag*>::value));
|
|
||||||
|
|
||||||
*i = v; // a good alternative could be something like write(x, v)
|
|
||||||
}
|
|
||||||
ValueType v;
|
|
||||||
Iterator i;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
class ConstantLvalueIteratorConcept {
|
|
||||||
public:
|
|
||||||
typedef typename std::iterator_traits<Iterator>::value_type value_type;
|
|
||||||
typedef typename std::iterator_traits<Iterator>::reference reference;
|
|
||||||
typedef typename boost::return_category<Iterator>::type return_category;
|
|
||||||
|
|
||||||
void constraints() {
|
|
||||||
boost::function_requires< ReadableIteratorConcept<Iterator> >();
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT((boost::is_convertible<return_category*,
|
|
||||||
boost::constant_lvalue_iterator_tag*>::value));
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT((boost::is_same<reference,
|
|
||||||
const value_type&>::value));
|
|
||||||
|
|
||||||
reference v = *i;
|
|
||||||
boost::ignore_unused_variable_warning(v);
|
|
||||||
}
|
|
||||||
Iterator i;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
class MutableLvalueIteratorConcept {
|
|
||||||
public:
|
|
||||||
typedef typename std::iterator_traits<Iterator>::value_type value_type;
|
|
||||||
typedef typename std::iterator_traits<Iterator>::reference reference;
|
|
||||||
typedef typename boost::return_category<Iterator>::type return_category;
|
|
||||||
|
|
||||||
void constraints() {
|
|
||||||
boost::function_requires< ReadableIteratorConcept<Iterator> >();
|
|
||||||
boost::function_requires<
|
|
||||||
WritableIteratorConcept<Iterator, value_type> >();
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT((boost::is_convertible<return_category*,
|
|
||||||
boost::mutable_lvalue_iterator_tag*>::value));
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT((boost::is_same<reference, value_type&>::value));
|
|
||||||
|
|
||||||
reference v = *i;
|
|
||||||
boost::ignore_unused_variable_warning(v);
|
|
||||||
}
|
|
||||||
Iterator i;
|
|
||||||
};
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
// Iterator Traversal Concepts
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
class ForwardIteratorConcept {
|
|
||||||
public:
|
|
||||||
typedef typename boost::traversal_category<Iterator>::type traversal_category;
|
|
||||||
|
|
||||||
void constraints() {
|
|
||||||
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
|
|
||||||
boost::function_requires< boost::EqualityComparableConcept<Iterator> >();
|
|
||||||
boost::function_requires<
|
|
||||||
boost::DefaultConstructibleConcept<Iterator> >();
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT((boost::is_convertible<traversal_category*,
|
|
||||||
boost::forward_traversal_tag*>::value));
|
|
||||||
++i;
|
|
||||||
(void)i++;
|
|
||||||
}
|
|
||||||
Iterator i;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
class BidirectionalIteratorConcept {
|
|
||||||
public:
|
|
||||||
typedef typename boost::traversal_category<Iterator>::type traversal_category;
|
|
||||||
|
|
||||||
void constraints() {
|
|
||||||
boost::function_requires< ForwardIteratorConcept<Iterator> >();
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT((boost::is_convertible<traversal_category*,
|
|
||||||
boost::bidirectional_traversal_tag*>::value));
|
|
||||||
|
|
||||||
--i;
|
|
||||||
(void)i--;
|
|
||||||
}
|
|
||||||
Iterator i;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
class RandomAccessIteratorConcept {
|
|
||||||
public:
|
|
||||||
typedef typename boost::traversal_category<Iterator>::type traversal_category;
|
|
||||||
typedef typename std::iterator_traits<Iterator>::difference_type
|
|
||||||
difference_type;
|
|
||||||
|
|
||||||
void constraints() {
|
|
||||||
boost::function_requires< BidirectionalIteratorConcept<Iterator> >();
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT((boost::is_convertible<traversal_category*,
|
|
||||||
boost::random_access_traversal_tag*>::value));
|
|
||||||
|
|
||||||
i += n;
|
|
||||||
i = i + n;
|
|
||||||
i = n + i;
|
|
||||||
i -= n;
|
|
||||||
i = i - n;
|
|
||||||
n = i - j;
|
|
||||||
}
|
|
||||||
difference_type n;
|
|
||||||
Iterator i, j;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace boost_concepts
|
|
||||||
|
|
||||||
|
|
||||||
#endif // BOOST_ITERATOR_CONCEPTS_HPP
|
|
@ -1,73 +0,0 @@
|
|||||||
#include <boost/iterator_concepts.hpp>
|
|
||||||
#include <boost/operators.hpp>
|
|
||||||
|
|
||||||
struct new_iterator
|
|
||||||
: public boost::iterator<std::random_access_iterator_tag, int>,
|
|
||||||
public boost::new_iterator_base
|
|
||||||
{
|
|
||||||
typedef boost::random_access_traversal_tag traversal_category;
|
|
||||||
typedef boost::mutable_lvalue_iterator_tag return_category;
|
|
||||||
|
|
||||||
int& operator*() const { return *m_x; }
|
|
||||||
new_iterator& operator++() { return *this; }
|
|
||||||
new_iterator operator++(int) { return *this; }
|
|
||||||
new_iterator& operator--() { return *this; }
|
|
||||||
new_iterator operator--(int) { return *this; }
|
|
||||||
new_iterator& operator+=(std::ptrdiff_t) { return *this; }
|
|
||||||
new_iterator operator+(std::ptrdiff_t) { return *this; }
|
|
||||||
new_iterator& operator-=(std::ptrdiff_t) { return *this; }
|
|
||||||
std::ptrdiff_t operator-(const new_iterator&) const { return 0; }
|
|
||||||
new_iterator operator-(std::ptrdiff_t) const { return *this; }
|
|
||||||
bool operator==(const new_iterator&) const { return false; }
|
|
||||||
bool operator!=(const new_iterator&) const { return false; }
|
|
||||||
bool operator<(const new_iterator&) const { return false; }
|
|
||||||
int* m_x;
|
|
||||||
};
|
|
||||||
new_iterator operator+(std::ptrdiff_t, new_iterator x) { return x; }
|
|
||||||
|
|
||||||
struct old_iterator
|
|
||||||
: public boost::iterator<std::random_access_iterator_tag, int>
|
|
||||||
{
|
|
||||||
int& operator*() const { return *m_x; }
|
|
||||||
old_iterator& operator++() { return *this; }
|
|
||||||
old_iterator operator++(int) { return *this; }
|
|
||||||
old_iterator& operator--() { return *this; }
|
|
||||||
old_iterator operator--(int) { return *this; }
|
|
||||||
old_iterator& operator+=(std::ptrdiff_t) { return *this; }
|
|
||||||
old_iterator operator+(std::ptrdiff_t) { return *this; }
|
|
||||||
old_iterator& operator-=(std::ptrdiff_t) { return *this; }
|
|
||||||
old_iterator operator-(std::ptrdiff_t) const { return *this; }
|
|
||||||
std::ptrdiff_t operator-(const old_iterator&) const { return 0; }
|
|
||||||
bool operator==(const old_iterator&) const { return false; }
|
|
||||||
bool operator!=(const old_iterator&) const { return false; }
|
|
||||||
bool operator<(const old_iterator&) const { return false; }
|
|
||||||
int* m_x;
|
|
||||||
};
|
|
||||||
old_iterator operator+(std::ptrdiff_t, old_iterator x) { return x; }
|
|
||||||
|
|
||||||
int
|
|
||||||
main()
|
|
||||||
{
|
|
||||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
|
||||||
boost::function_requires<
|
|
||||||
boost_concepts::MutableLvalueIteratorConcept<int*> >();
|
|
||||||
boost::function_requires<
|
|
||||||
boost_concepts::RandomAccessIteratorConcept<int*> >();
|
|
||||||
|
|
||||||
boost::function_requires<
|
|
||||||
boost_concepts::ConstantLvalueIteratorConcept<const int*> >();
|
|
||||||
boost::function_requires<
|
|
||||||
boost_concepts::RandomAccessIteratorConcept<const int*> >();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
boost::function_requires<
|
|
||||||
boost_concepts::MutableLvalueIteratorConcept<new_iterator> >();
|
|
||||||
boost::function_requires<
|
|
||||||
boost_concepts::RandomAccessIteratorConcept<new_iterator> >();
|
|
||||||
|
|
||||||
boost::function_requires<
|
|
||||||
boost_concepts::MutableLvalueIteratorConcept<old_iterator> >();
|
|
||||||
boost::function_requires<
|
|
||||||
boost_concepts::RandomAccessIteratorConcept<old_iterator> >();
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,160 +0,0 @@
|
|||||||
<html>
|
|
||||||
<!--
|
|
||||||
-- Copyright (c) Jeremy Siek 2000,2001
|
|
||||||
--
|
|
||||||
-- Permission to use, copy, modify, distribute and sell this software
|
|
||||||
-- and its documentation for any purpose is hereby granted without fee,
|
|
||||||
-- provided that the above copyright notice appears in all copies and
|
|
||||||
-- that both that copyright notice and this permission notice appear
|
|
||||||
-- in supporting documentation. I make no representations about the
|
|
||||||
-- suitability of this software for any purpose. It is provided "as is"
|
|
||||||
-- without express or implied warranty.
|
|
||||||
-->
|
|
||||||
<head>
|
|
||||||
<title>Boost Iterator Traits</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
|
||||||
ALINK="#ff0000">
|
|
||||||
<IMG SRC="../../../../c++boost.gif"
|
|
||||||
ALT="C++ Boost" width="277" height="86">
|
|
||||||
<BR Clear>
|
|
||||||
|
|
||||||
<h1>Boost Iterator Category Traits</h1>
|
|
||||||
Header <tt><a href="../../boost/iterator_categories.hpp">boost/iterator_categories.hpp</a></tt>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The <tt>boost::traversal_category</tt> and
|
|
||||||
<tt>boost::return_category</tt> traits classes provides access to the
|
|
||||||
category tags for iterators that model the Boost <a
|
|
||||||
href="./iterator_concepts.htm">Iterator Concepts</a>, which are a
|
|
||||||
replacement for the iterator requirements in the C++ standard. The
|
|
||||||
other associated types of the Boost iterator concepts are accessed
|
|
||||||
through the <tt>std::iterator_traits</tt> class.
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><tt>traversal_category<Iter>::type</tt> Can the iterator go forward, backward, etc.?
|
|
||||||
<li><tt>return_category<Iter>::type</tt> Is the iterator read or write only?
|
|
||||||
Is the dereferenced type an lvalue?
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
An important feature of the <tt>boost::traversal_category</tt> and
|
|
||||||
<tt>boost::return_category</tt> classes is that they are <b>backwards
|
|
||||||
compatible</b>, i.e., they automatically work for iterators for which
|
|
||||||
there are valid definitions of <tt>std::iterator_traits</tt>. The old
|
|
||||||
<tt>iterator_category</tt> is mapped to the appropriate traversal and
|
|
||||||
return categories.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
When creating a new iterator type that is meant to work with
|
|
||||||
<tt>boost::traversal_category</tt> and
|
|
||||||
<tt>boost::return_category</tt>, you can either create a
|
|
||||||
specialization of these classes for your iterator type, or you can
|
|
||||||
provide all the necessary associated types as nested typedefs. In
|
|
||||||
this case, your iterator class will need to inherit from
|
|
||||||
<tt>new_iterator_base</tt> to let the category traits know
|
|
||||||
that it will be able to find typedefs for <tt>traversal_category</tt>
|
|
||||||
and <tt>return_category</tt> in you iterator class.
|
|
||||||
|
|
||||||
|
|
||||||
Each of the new iterator requirements will need a category tag.
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
// Return Type Categories
|
|
||||||
struct readable_iterator_tag { };
|
|
||||||
struct writable_iterator_tag { };
|
|
||||||
struct swappable_iterator_tag { };
|
|
||||||
struct mutable_lvalue_iterator_tag : virtual public writable_iterator_tag,
|
|
||||||
virtual public readable_iterator_tag { };
|
|
||||||
struct constant_lvalue_iterator_tag : public readable_iterator_tag { };
|
|
||||||
|
|
||||||
// Traversal Categories
|
|
||||||
struct forward_traversal_tag { };
|
|
||||||
struct bidirectional_traversal_tag : public forward_traversal_tag { };
|
|
||||||
struct random_access_traversal_tag : public bidirectional_traversal_tag { };
|
|
||||||
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The following is pseudo-code for the iterator category traits classes.
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
<i>// Inherit from iterator_base if your iterator defines its own
|
|
||||||
// return_category and traversal_category. Otherwise, the "old style"
|
|
||||||
// iterator category will be mapped to the return_category and
|
|
||||||
// traversal_category.</i>
|
|
||||||
struct new_iterator_base { };
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
struct return_category
|
|
||||||
{
|
|
||||||
<b><i>// Pseudo-code</i></b>
|
|
||||||
if (Iterator inherits from new_iterator_base) {
|
|
||||||
typedef typename Iterator::return_category type;
|
|
||||||
} else {
|
|
||||||
typedef std::iterator_traits<Iterator> OldTraits;
|
|
||||||
typedef typename OldTraits::iterator_category Cat;
|
|
||||||
if (Cat inherits from std::forward_iterator_tag)
|
|
||||||
if (is-const(T))
|
|
||||||
typedef boost::constant_lvalue_iterator_tag type;
|
|
||||||
else
|
|
||||||
typedef boost::mutable_lvalue_iterator_tag type;
|
|
||||||
else if (Cat inherits from std::input_iterator_tag)
|
|
||||||
typedef boost::readable_iterator_tag type;
|
|
||||||
else if (Cat inherits from std::output_iterator_tag)
|
|
||||||
typedef boost::writable_iterator_tag type;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct return_category<T*>
|
|
||||||
{
|
|
||||||
<b><i>// Pseudo-code</i></b>
|
|
||||||
if (is-const(T))
|
|
||||||
typedef boost::constant_lvalue_iterator_tag type;
|
|
||||||
else
|
|
||||||
typedef boost::mutable_lvalue_iterator_tag type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
struct traversal_category
|
|
||||||
{
|
|
||||||
<b><i>// Pseudo-code</i></b>
|
|
||||||
if (Iterator inherits from new_iterator_base) {
|
|
||||||
typedef typename Iterator::traversal_category type;
|
|
||||||
} else {
|
|
||||||
typedef std::iterator_traits<Iterator> OldTraits;
|
|
||||||
typedef typename OldTraits::iterator_category Cat;
|
|
||||||
|
|
||||||
if (Cat inherits from std::random_access_iterator_tag)
|
|
||||||
typedef boost::random_access_traversal_tag type;
|
|
||||||
else if (Cat inherits from std::bidirectional_iterator_tag)
|
|
||||||
typedef boost::bidirectional_traversal_tag type;
|
|
||||||
else if (Cat inherits from std::forward_iterator_tag)
|
|
||||||
typedef boost::forward_traversal_tag type;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct traversal_category<T*>
|
|
||||||
{
|
|
||||||
typedef boost::random_access_traversal_tag type;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<address><a href="mailto:jsiek@lsc.nd.edu">jeremy siek</a></address>
|
|
||||||
<!-- Created: Sun Mar 18 14:06:57 EST 2001 -->
|
|
||||||
<!-- hhmts start -->
|
|
||||||
Last modified: Mon Mar 19 12:59:30 EST 2001
|
|
||||||
<!-- hhmts end -->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,37 +0,0 @@
|
|||||||
#FIG 3.2
|
|
||||||
Landscape
|
|
||||||
Center
|
|
||||||
Inches
|
|
||||||
Letter
|
|
||||||
100.00
|
|
||||||
Single
|
|
||||||
-2
|
|
||||||
1200 2
|
|
||||||
6 150 2325 4275 4350
|
|
||||||
2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 1 0 2
|
|
||||||
1 1 1.00 60.00 120.00
|
|
||||||
1725 4050 1725 3450
|
|
||||||
2 1 0 1 0 7 100 0 -1 4.000 0 0 -1 1 0 2
|
|
||||||
1 1 1.00 60.00 120.00
|
|
||||||
1725 3150 1725 2550
|
|
||||||
4 0 0 100 0 19 18 0.0000 4 210 3180 375 2550 ForwardTraversalIterator\001
|
|
||||||
4 0 0 100 0 19 18 0.0000 4 210 3765 225 3450 BidirectionalTraversalIterator\001
|
|
||||||
4 0 0 100 0 19 18 0.0000 4 210 4125 150 4350 RandomAccessTraversalIterator\001
|
|
||||||
-6
|
|
||||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
|
||||||
1 1 1.00 60.00 120.00
|
|
||||||
4800 3600 4800 2400
|
|
||||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
|
||||||
1 1 1.00 60.00 120.00
|
|
||||||
6900 3000 5400 2400
|
|
||||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
|
||||||
1 1 1.00 60.00 120.00
|
|
||||||
6900 3000 7500 2400
|
|
||||||
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
|
|
||||||
1 1 1.00 60.00 120.00
|
|
||||||
6900 3000 9075 2475
|
|
||||||
4 0 0 100 0 19 18 0.0000 4 210 2040 6600 2400 WritableIterator\001
|
|
||||||
4 0 0 100 0 19 18 0.0000 4 210 2145 3900 2400 ReadableIterator\001
|
|
||||||
4 0 0 50 0 19 18 0.0000 4 210 2835 5700 3300 MutableLvalueIterator\001
|
|
||||||
4 0 0 50 0 19 18 0.0000 4 270 2355 9075 2400 SwappableIterator\001
|
|
||||||
4 0 0 50 0 19 18 0.0000 4 210 2970 3825 3900 ConstantLvalueIterator\001
|
|
Binary file not shown.
Before Width: | Height: | Size: 3.2 KiB |
@ -1,663 +0,0 @@
|
|||||||
<HTML>
|
|
||||||
<!--
|
|
||||||
-- Copyright (c) Jeremy Siek 2000
|
|
||||||
--
|
|
||||||
-- Permission to use, copy, modify, distribute and sell this software
|
|
||||||
-- and its documentation for any purpose is hereby granted without fee,
|
|
||||||
-- provided that the above copyright notice appears in all copies and
|
|
||||||
-- that both that copyright notice and this permission notice appear
|
|
||||||
-- in supporting documentation. I make no representations about the
|
|
||||||
-- suitability of this software for any purpose. It is provided "as is"
|
|
||||||
-- without express or implied warranty.
|
|
||||||
-->
|
|
||||||
<!--
|
|
||||||
-- Copyright (c) 1996-1999
|
|
||||||
-- Silicon Graphics Computer Systems, Inc.
|
|
||||||
--
|
|
||||||
-- Permission to use, copy, modify, distribute and sell this software
|
|
||||||
-- and its documentation for any purpose is hereby granted without fee,
|
|
||||||
-- provided that the above copyright notice appears in all copies and
|
|
||||||
-- that both that copyright notice and this permission notice appear
|
|
||||||
-- in supporting documentation. Silicon Graphics makes no
|
|
||||||
-- representations about the suitability of this software for any
|
|
||||||
-- purpose. It is provided "as is" without express or implied warranty.
|
|
||||||
--
|
|
||||||
-- Copyright (c) 1994
|
|
||||||
-- Hewlett-Packard Company
|
|
||||||
--
|
|
||||||
-- Permission to use, copy, modify, distribute and sell this software
|
|
||||||
-- and its documentation for any purpose is hereby granted without fee,
|
|
||||||
-- provided that the above copyright notice appears in all copies and
|
|
||||||
-- that both that copyright notice and this permission notice appear
|
|
||||||
-- in supporting documentation. Hewlett-Packard Company makes no
|
|
||||||
-- representations about the suitability of this software for any
|
|
||||||
-- purpose. It is provided "as is" without express or implied warranty.
|
|
||||||
--
|
|
||||||
-->
|
|
||||||
<Head>
|
|
||||||
<Title>Iterator Concepts</Title>
|
|
||||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
|
||||||
ALINK="#ff0000">
|
|
||||||
<IMG SRC="../../../../c++boost.gif"
|
|
||||||
ALT="C++ Boost" width="277" height="86">
|
|
||||||
|
|
||||||
<BR Clear>
|
|
||||||
|
|
||||||
|
|
||||||
<h1>Iterator Concepts</h1>
|
|
||||||
|
|
||||||
<p>The standard iterator categories and requirements are flawed because
|
|
||||||
they use a single hierarchy of requirements to address two orthogonal
|
|
||||||
issues: <b><i>iterator traversal</i></b> and <b><i>dereference return
|
|
||||||
type</i></b>. The current iterator requirement hierarchy is mainly
|
|
||||||
geared towards iterator traversal (hence the category names), while
|
|
||||||
requirements that address dereference return type sneak in at various
|
|
||||||
places.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The iterator requirements should be separated into two hierarchies.
|
|
||||||
One set of concepts handles the return type semantics:
|
|
||||||
<ul>
|
|
||||||
<li><a href="#concept:ReadableIterator">Readable Iterator</a></li>
|
|
||||||
<li><a href="#concept:WritableIterator">Writable Iterator</a></li>
|
|
||||||
<li><a href="#concept:SwappableIterator">Swappable Iterator</a></li>
|
|
||||||
<li><a href="#concept:ConstantLvalueIterator">Constant Lvalue Iterator</a></li>
|
|
||||||
<li><a href="#concept:MutableLvalueIterator">Mutable Lvalue Iterator</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
The other set of concepts handles iterator traversal:
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="#concept:ForwardTraversalIterator">Forward Traversal Iterator</a></li>
|
|
||||||
<li><a href="#concept:BidirectionalTraversalIterator">Bidirectional Traversal Iterator</a></li>
|
|
||||||
<li><a href="#concept:RandomAccessTraversalIterator">Random Access Traversal Iterator</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
The current Input Iterator and Output Iterator requirements will
|
|
||||||
continue to be used as is. Note that Input Iterator implies Readable
|
|
||||||
Iterator and Output Iterator implies Writable Iterator.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Note: we considered defining a Single-Pass Iterator, which could be
|
|
||||||
combined with Readable or Writable Iterator to replace the Input and
|
|
||||||
Output Iterator requirements. We rejected this idea because there are
|
|
||||||
some differences between Input and Output Iterators that make it hard
|
|
||||||
to merge them: for example Input Iterator requires Equality Comparable
|
|
||||||
while Output Iterator does not.
|
|
||||||
|
|
||||||
|
|
||||||
<p></p>
|
|
||||||
<DIV ALIGN="CENTER"><A NAME="fig:graph-concepts"></A></A>
|
|
||||||
<TABLE>
|
|
||||||
<CAPTION ALIGN="TOP"><STRONG>Figure 1:</STRONG>
|
|
||||||
The iterator concepts and refinement relationships.
|
|
||||||
</CAPTION>
|
|
||||||
<TR><TD><IMG SRC="./iterator_concepts.gif" ></TD></TR>
|
|
||||||
</TABLE>
|
|
||||||
</DIV>
|
|
||||||
<p></p>
|
|
||||||
|
|
||||||
|
|
||||||
<h2>Relationship with the standard iterator concepts</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
std::Input Iterator implies boost::ReadableIterator.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
std::Output Iterator implies boost::Writable Iterator.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
std::Forward Iterator refines boost::Forward Iterator and
|
|
||||||
boost::Constant Lvalue Iterator or boost::Mutable Lvalue Iterator.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
std::Bidirectional Iterator refines boost::Bidirectional Iterator and
|
|
||||||
boost::Constant Lvalue Iterator or boost::Mutable Lvalue Iterator.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
std::Random Access Iterator refines boost::Random Access Iterator and
|
|
||||||
boost::Constant Lvalue Iterator or boost::Mutable Lvalue Iterator.
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Notation</h3>
|
|
||||||
<Table>
|
|
||||||
<tr>
|
|
||||||
<td><tt>X</tt></td>
|
|
||||||
<td>The iterator type.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><tt>T</tt></td>
|
|
||||||
<td>The value type of <tt>X</tt>, i.e., <tt>std::iterator_traits<X>::value_type</tt>.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><tt>x</tt>, <tt>y</tt></td>
|
|
||||||
<td>An object of type <tt>X</tt>.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><tt>t</tt></td>
|
|
||||||
<td>An object of type <tt>T</tt>.</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<!--------------------------------------------------------------------------->
|
|
||||||
|
|
||||||
<H3><A NAME="concept:ReadableIterator"></A>
|
|
||||||
Readable Iterator
|
|
||||||
</H3>
|
|
||||||
|
|
||||||
A Readable Iterator is an iterator that dereferences to produce an
|
|
||||||
rvalue that is convertible to the <tt>value_type</tt> of the
|
|
||||||
iterator.
|
|
||||||
|
|
||||||
<h3>Associated Types</h3>
|
|
||||||
|
|
||||||
<Table border>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>Value type</td>
|
|
||||||
<td><tt>std::iterator_traits<X>::value_type</tt></td>
|
|
||||||
<td>The type of the objects pointed to by the iterator.</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>Reference type</td>
|
|
||||||
<td><tt>std::iterator_traits<X>::reference</tt></td>
|
|
||||||
<td>
|
|
||||||
The return type of dereferencing the iterator. This
|
|
||||||
type must be convertible to <tt>T</tt>.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>Return Category</td>
|
|
||||||
<td><tt>std::return_category<X>::type</tt></td>
|
|
||||||
<td>
|
|
||||||
A type convertible to <tt>std::readable_iterator_tag</tt>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</Table>
|
|
||||||
|
|
||||||
<h3>Refinement of</h3>
|
|
||||||
|
|
||||||
<A href="http://www.boost.org/libs/utility/CopyConstructible.html">Copy Constructible</A>
|
|
||||||
|
|
||||||
<h3>Valid expressions</h3>
|
|
||||||
|
|
||||||
<Table border>
|
|
||||||
<tr><TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH><TH>Return type</TH></tr>
|
|
||||||
<tr>
|
|
||||||
<td>Dereference</td>
|
|
||||||
<td><tt>*x</tt></td>
|
|
||||||
<td> </td>
|
|
||||||
<td><tt>std::iterator_traits<X>::reference</tt></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Member access</td>
|
|
||||||
<td><tt>x->m</tt></td>
|
|
||||||
<td><tt>T</tt> is a type with a member named <tt>m</tt>.</td>
|
|
||||||
<td>
|
|
||||||
If <tt>m</tt> is a data member, the type of <tt>m</tt>.
|
|
||||||
If <tt>m</tt> is a member function, the return type of <tt>m</tt>.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<!--------------------------------------------------------------------------->
|
|
||||||
|
|
||||||
<H3><A NAME="concept:WritableIterator"></A>
|
|
||||||
Writable Iterator
|
|
||||||
</H3>
|
|
||||||
|
|
||||||
A Writable Iterator is an iterator that can be used to store a value
|
|
||||||
using the dereference-assignment expression.
|
|
||||||
|
|
||||||
<h3>Definitions</h3>
|
|
||||||
|
|
||||||
If <tt>x</tt> is an Writable Iterator of type <tt>X</tt>, then the
|
|
||||||
expression <tt>*x = a;</tt> stores the value <tt>a</tt> into
|
|
||||||
<tt>x</tt>. Note that <tt>operator=</tt>, like other C++ functions,
|
|
||||||
may be overloaded; it may, in fact, even be a template function. In
|
|
||||||
general, then, <tt>a</tt> may be any of several different types. A
|
|
||||||
type <tt>A</tt> belongs to the <i>set of value types</i> of <tt>X</tt>
|
|
||||||
if, for an object <tt>a</tt> of type <tt>A</tt>, <tt>*x = a;</tt> is
|
|
||||||
well-defined and does not require performing any non-trivial
|
|
||||||
conversions on <tt>a</tt>.
|
|
||||||
|
|
||||||
<h3>Associated Types</h3>
|
|
||||||
|
|
||||||
<Table border>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>Return Category</td>
|
|
||||||
<td><tt>std::return_category<X>::type</tt></td>
|
|
||||||
<td>
|
|
||||||
A type convertible to <tt>std::writable_iterator_tag</tt>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</Table>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Refinement of</h3>
|
|
||||||
|
|
||||||
<A href="http://www.boost.org/libs/utility/CopyConstructible.html">Copy Constructible</A>
|
|
||||||
|
|
||||||
<h3>Valid expressions</h3>
|
|
||||||
|
|
||||||
<Table border>
|
|
||||||
<tr>
|
|
||||||
<TH>Name</TH><TH>Expression</TH><TH>Return type</TH>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Dereference assignment</td>
|
|
||||||
<td><tt>*x = a</tt></td>
|
|
||||||
<td>unspecified</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<!--------------------------------------------------------------------------->
|
|
||||||
|
|
||||||
<H3><A NAME="concept:SwappableIterator"></A>
|
|
||||||
Swappable Iterator
|
|
||||||
</H3>
|
|
||||||
|
|
||||||
A Swappable Iterator is an iterator whose dereferenced values can be
|
|
||||||
swapped.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Note: the requirements for Swappable Iterator are dependent on the
|
|
||||||
issues surrounding <tt>std::swap()</tt> being resolved. Here we assume
|
|
||||||
that the issue will be resolved by allowing the overload of
|
|
||||||
<tt>std::swap()</tt> for user-defined types.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Note: Readable Iterator and Writable Iterator combined implies
|
|
||||||
Swappable Iterator because of the fully templated
|
|
||||||
<tt>std::swap()</tt>. However, Swappable Iterator does not imply
|
|
||||||
Readable Iterator nor Writable Iterator.
|
|
||||||
|
|
||||||
<h3>Associated Types</h3>
|
|
||||||
|
|
||||||
<Table border>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>Return Category</td>
|
|
||||||
<td><tt>std::return_category<X>::type</tt></td>
|
|
||||||
<td>
|
|
||||||
A type convertible to <tt>std::swappable_iterator_tag</tt>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</Table>
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Valid expressions</h3>
|
|
||||||
|
|
||||||
Of the two valid expressions listed below, only one <b>OR</b> the
|
|
||||||
other is required. If <tt>std::iter_swap()</tt> is overloaded for
|
|
||||||
<tt>X</tt> then <tt>std::swap()</tt> is not required. If
|
|
||||||
<tt>std::iter_swap()</tt> is not overloaded for <tt>X</tt> then the
|
|
||||||
default (fully templated) version is used, which will call
|
|
||||||
<tt>std::swap()</tt> (this means changing the current requirements for
|
|
||||||
<tt>std::iter_swap()</tt>).
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<Table border>
|
|
||||||
<tr>
|
|
||||||
<TH>Name</TH><TH>Expression</TH><TH>Return type</TH>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>Iterator Swap</td>
|
|
||||||
<td><tt>std::iter_swap(x, y)</tt></td>
|
|
||||||
<td>void</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>Dereference and Swap</td>
|
|
||||||
<td><tt>std::swap(*x, *y)</tt></td>
|
|
||||||
<td>void</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<!--------------------------------------------------------------------------->
|
|
||||||
|
|
||||||
<H3><A NAME="concept:ConstantLvalueIterator"></A>
|
|
||||||
Constant Lvalue Iterator
|
|
||||||
</H3>
|
|
||||||
|
|
||||||
A Constant Lvalue Iterator is an iterator that dereferences to produce a
|
|
||||||
const reference to the pointed-to object, i.e., the associated
|
|
||||||
<tt>reference</tt> type is <tt>const T&</tt>. Changing the value
|
|
||||||
of or destroying an iterator that models Constant Lvalue Iterator does
|
|
||||||
not invalidate pointers and references previously obtained from that
|
|
||||||
iterator.
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Refinement of</h3>
|
|
||||||
|
|
||||||
<a href="#concept:ReadableIterator">Readable Iterator</a>
|
|
||||||
|
|
||||||
<h3>Associated Types</h3>
|
|
||||||
|
|
||||||
<Table border>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>Reference type</td>
|
|
||||||
<td><tt>std::iterator_traits<X>::reference</tt></td>
|
|
||||||
<td>
|
|
||||||
The return type of dereferencing the iterator, which must be
|
|
||||||
<tt>const T&</tt>.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-- I don't think this is needed
|
|
||||||
<tr>
|
|
||||||
<td>Pointer type</td>
|
|
||||||
<td><tt>std::iterator_traits<X>::pointer</tt></td>
|
|
||||||
<td>
|
|
||||||
The pointer to the value type, which must be <tt>const T*</tt>.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>Return Category</td>
|
|
||||||
<td><tt>std::return_category<X>::type</tt></td>
|
|
||||||
<td>
|
|
||||||
A type convertible to <tt>std::constant_lvalue_iterator_tag</tt>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<!-- these are not necessary now that we use reference as operator* return type
|
|
||||||
<h3>Valid expressions</h3>
|
|
||||||
|
|
||||||
<Table border>
|
|
||||||
<tr><TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH><TH>Return type</TH></tr>
|
|
||||||
<tr>
|
|
||||||
<td>Dereference</td>
|
|
||||||
<td><tt>*x</tt></td>
|
|
||||||
<td> </td>
|
|
||||||
<td><tt>std::iterator_traits<X>::reference</tt></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Member access</td>
|
|
||||||
<td><tt>x->m</tt></td>
|
|
||||||
<td><tt>T</tt> is a type with a member named <tt>m</tt>.</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
<p>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<!--------------------------------------------------------------------------->
|
|
||||||
|
|
||||||
<H3><A NAME="concept:MutableLvalueIterator"></A>
|
|
||||||
Mutable Lvalue Iterator
|
|
||||||
</H3>
|
|
||||||
|
|
||||||
A Mutable Lvalue Iterator is an iterator that dereferences to produce a
|
|
||||||
reference to the pointed-to object. The associated <tt>reference</tt>
|
|
||||||
type is <tt>T&</tt>. Changing the value of or destroying an
|
|
||||||
iterator that models Mutable Lvalue Iterator does not invalidate
|
|
||||||
pointers and references previously obtained from that iterator.
|
|
||||||
|
|
||||||
<h3>Refinement of</h3>
|
|
||||||
|
|
||||||
<a href="#concept:ReadableIterator">Readable Iterator</a>,
|
|
||||||
<a href="#concept:WritableIterator">Writable Iterator</a>,
|
|
||||||
and <a href="#concept:SwappableIterator">Swappable Iterator</a>.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Associated Types</h3>
|
|
||||||
|
|
||||||
<Table border>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>Reference type</td>
|
|
||||||
<td><tt>std::iterator_traits<X>::reference</tt></td>
|
|
||||||
<td>The return type of dereferencing the iterator, which must be
|
|
||||||
<tt>T&</tt>.</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-- I don't think this is necessary
|
|
||||||
<tr>
|
|
||||||
<td>Pointer type</td>
|
|
||||||
<td><tt>std::iterator_traits<X>::pointer</tt></td>
|
|
||||||
<td>
|
|
||||||
The pointer to the value type, which is <tt>T*</tt>.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>Return Category</td>
|
|
||||||
<td><tt>std::return_category<X>::type</tt></td>
|
|
||||||
<td>
|
|
||||||
A type convertible to <tt>std::mutable_lvalue_iterator_tag</tt>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<!-- no longer needed since the return type is specified as reference in the readable iterator
|
|
||||||
<h3>Valid expressions</h3>
|
|
||||||
|
|
||||||
<Table border>
|
|
||||||
<tr><TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH><TH>Return type</TH></tr>
|
|
||||||
<tr>
|
|
||||||
<td>Dereference</td>
|
|
||||||
<td><tt>*x</tt></td>
|
|
||||||
<td> </td>
|
|
||||||
<td><tt>std::iterator_traits<X>::reference</tt></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Member access</td>
|
|
||||||
<td><tt>x->m</tt></td>
|
|
||||||
<td><tt>T</tt> is a type with a member named <tt>m</tt>.</td>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<hr>
|
|
||||||
<!--------------------------------------------------------------------------->
|
|
||||||
|
|
||||||
<H3><A NAME="concept:ForwardTraversalIterator"></A>
|
|
||||||
Forward Traversal Iterator
|
|
||||||
</H3>
|
|
||||||
|
|
||||||
The Forward Iterator is an iterator that can be incremented. Also, it
|
|
||||||
is permissible to make multiple passes through the iterator's range.
|
|
||||||
|
|
||||||
<h3>Refinement of</h3>
|
|
||||||
|
|
||||||
<A href="http://www.boost.org/libs/utility/CopyConstructible.html">Copy Constructible</A>,
|
|
||||||
<A href="http://www.boost.org/libs/utility/Assignable.html">Assignable</A>,
|
|
||||||
<A href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default Constructible</A>, and
|
|
||||||
<A href="http://www.sgi.com/tech/stl/EqualityComparable.html">Equality Comparable</A>
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Associated types</h3>
|
|
||||||
|
|
||||||
<Table border>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>Difference Type</td>
|
|
||||||
<td><tt>std::iterator_traits<X>::difference_type</tt></td>
|
|
||||||
<td>
|
|
||||||
A signed integral type used for representing distances
|
|
||||||
between iterators that point into the same range.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>Traversal Category</td>
|
|
||||||
<td><tt>std::traversal_category<X>::type</tt></td>
|
|
||||||
<td>
|
|
||||||
A type convertible to <tt>std::forward_traversal_tag</tt>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</Table>
|
|
||||||
|
|
||||||
<h3>Valid expressions</h3>
|
|
||||||
|
|
||||||
<Table border>
|
|
||||||
<tr>
|
|
||||||
<TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH>
|
|
||||||
<TH>Return type</TH>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Preincrement</td>
|
|
||||||
<td><tt>++i</tt></td><td> </td><td><tt>X&</tt></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Postincrement</td>
|
|
||||||
<td><tt>i++</tt></td><td> </td><td>convertible to <tt>const X&</tt></td>
|
|
||||||
</tr>
|
|
||||||
</Table>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<hr>
|
|
||||||
<!--------------------------------------------------------------------------->
|
|
||||||
|
|
||||||
<H3><A NAME="concept:BidirectionalTraversalIterator"></A>
|
|
||||||
Bidirectional Traversal Iterator
|
|
||||||
</H3>
|
|
||||||
|
|
||||||
An iterator that can be incremented and decremented.
|
|
||||||
|
|
||||||
<h3>Refinement of</h3>
|
|
||||||
|
|
||||||
<a href="#concept:ForwardTraversalIterator">Forward Traversal Iterator</a>
|
|
||||||
|
|
||||||
<h3>Associated types</h3>
|
|
||||||
|
|
||||||
<Table border>
|
|
||||||
<tr>
|
|
||||||
<td>Traversal Category</td>
|
|
||||||
<td><tt>std::traversal_category<X>::type</tt></td>
|
|
||||||
<td>
|
|
||||||
A type convertible to <tt>std::bidirectional_traversal_tag</tt>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</Table>
|
|
||||||
|
|
||||||
<h3>Valid expressions</h3>
|
|
||||||
|
|
||||||
<Table border>
|
|
||||||
<tr>
|
|
||||||
<TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH>
|
|
||||||
<TH>Return type</TH>
|
|
||||||
</tr>
|
|
||||||
<tr><td>Predecrement</td>
|
|
||||||
<td><tt>--i</tt></td><td> </td><td><tt>X&</tt></td>
|
|
||||||
</tr>
|
|
||||||
<tr><td>Postdecrement</td>
|
|
||||||
<td><tt>i--</tt></td><td> </td><td>convertible to <tt>const X&</tt></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<hr>
|
|
||||||
<!--------------------------------------------------------------------------->
|
|
||||||
|
|
||||||
<H3><A NAME="concept:RandomAccessTraversalIterator"></A>
|
|
||||||
Random Access Traversal Iterator
|
|
||||||
</H3>
|
|
||||||
|
|
||||||
An iterator that provides constant-time methods for moving forward and
|
|
||||||
backward in arbitrary-sized steps.
|
|
||||||
|
|
||||||
<h3>Refinement of</h3>
|
|
||||||
|
|
||||||
<a href="#concept:BidirectionalTraversalIterator">Bidirectional Traversal Iterator</a> and
|
|
||||||
<A href="http://www.sgi.com/tech/stl/LessThanComparable.html">Less Than Comparable</A> where <tt><</tt> is a total ordering
|
|
||||||
|
|
||||||
<h3>Associated types</h3>
|
|
||||||
|
|
||||||
<Table border>
|
|
||||||
<tr>
|
|
||||||
<td>Traversal Category</td>
|
|
||||||
<td><tt>std::traversal_category<X>::type</tt></td>
|
|
||||||
<td>
|
|
||||||
A type convertible to <tt>std::random_access_traversal_tag</tt>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</Table>
|
|
||||||
|
|
||||||
<h3>Valid expressions</h3>
|
|
||||||
|
|
||||||
<Table border>
|
|
||||||
<tr><TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH>
|
|
||||||
<TH>Return type</TH>
|
|
||||||
</tr>
|
|
||||||
<tr><td>Iterator addition</td>
|
|
||||||
<td><tt>i += n</tt></td><td> </td><td><tt>X&</tt></td>
|
|
||||||
</tr>
|
|
||||||
<tr><td>Iterator addition</td>
|
|
||||||
<td><tt>i + n</tt> or <tt>n + i</tt></td><td> </td><td><tt>X</tt></td>
|
|
||||||
</tr>
|
|
||||||
<tr><td>Iterator subtraction</td>
|
|
||||||
<td><tt>i -= n</tt></td><td> </td><td><tt>X&</tt></td>
|
|
||||||
</tr>
|
|
||||||
<tr><td>Iterator subtraction</td>
|
|
||||||
<td><tt>i - n</tt></td><td> </td><td><tt>X</tt></td>
|
|
||||||
</tr>
|
|
||||||
<tr><td>Difference</td>
|
|
||||||
<td><tt>i - j</tt></td><td> </td><td><tt>std::iterator_traits<X>::difference_type</tt></td>
|
|
||||||
</tr>
|
|
||||||
<tr><td>Element operator</td>
|
|
||||||
<td><tt>i[n]</tt></td>
|
|
||||||
<td><tt>X</tt> must also be a model of
|
|
||||||
<a href="#concept:ReadableIterator">Readable Iterator</a>. </td>
|
|
||||||
<td><tt>std::iterator_traits<X>::reference</tt></td>
|
|
||||||
</tr>
|
|
||||||
<tr><td>Element assignment</td>
|
|
||||||
<td><tt>i[n] = t</tt></td>
|
|
||||||
<td><tt>X</tt> must also be a model of
|
|
||||||
<a href="#concept:WritableIterator">Writable Iterator</a>.</td>
|
|
||||||
<td>unspecified</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
<TABLE>
|
|
||||||
<TR valign=top>
|
|
||||||
<TD nowrap>Copyright © 2000</TD><TD>
|
|
||||||
<A HREF="../../../../people/jeremy_siek.htm">Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
|
|
||||||
</TD></TR></TABLE>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,55 +0,0 @@
|
|||||||
// (C) Copyright Jeremy Siek 2001. Permission to copy, use, modify,
|
|
||||||
// sell and distribute this software is granted provided this
|
|
||||||
// copyright notice appears in all copies. This software is provided
|
|
||||||
// "as is" without express or implied warranty, and with no claim as
|
|
||||||
// to its suitability for any purpose.
|
|
||||||
|
|
||||||
// Revision History:
|
|
||||||
|
|
||||||
// 27 Feb 2001 Jeremy Siek
|
|
||||||
// Initial checkin.
|
|
||||||
|
|
||||||
#ifndef BOOST_FUNCTION_OUTPUT_ITERATOR_HPP
|
|
||||||
#define BOOST_FUNCTION_OUTPUT_ITERATOR_HPP
|
|
||||||
|
|
||||||
#include <iterator>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
template <class UnaryFunction>
|
|
||||||
class function_output_iterator {
|
|
||||||
typedef function_output_iterator self;
|
|
||||||
public:
|
|
||||||
typedef std::output_iterator_tag iterator_category;
|
|
||||||
typedef void value_type;
|
|
||||||
typedef void difference_type;
|
|
||||||
typedef void pointer;
|
|
||||||
typedef void reference;
|
|
||||||
|
|
||||||
explicit function_output_iterator(const UnaryFunction& f = UnaryFunction())
|
|
||||||
: m_f(f) {}
|
|
||||||
|
|
||||||
struct output_proxy {
|
|
||||||
output_proxy(UnaryFunction& f) : m_f(f) { }
|
|
||||||
template <class T> output_proxy& operator=(const T& value) {
|
|
||||||
m_f(value);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
UnaryFunction& m_f;
|
|
||||||
};
|
|
||||||
output_proxy operator*() { return output_proxy(m_f); }
|
|
||||||
self& operator++() { return *this; }
|
|
||||||
self& operator++(int) { return *this; }
|
|
||||||
private:
|
|
||||||
UnaryFunction m_f;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class UnaryFunction>
|
|
||||||
inline function_output_iterator<UnaryFunction>
|
|
||||||
make_function_output_iterator(const UnaryFunction& f = UnaryFunction()) {
|
|
||||||
return function_output_iterator<UnaryFunction>(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#endif // BOOST_FUNCTION_OUTPUT_ITERATOR_HPP
|
|
@ -1,426 +0,0 @@
|
|||||||
// (C) Copyright Jeremy Siek and David Abrahams 2000-2001. Permission to copy,
|
|
||||||
// use, modify, sell and distribute this software is granted provided this
|
|
||||||
// copyright notice appears in all copies. This software is provided "as is"
|
|
||||||
// without express or implied warranty, and with no claim as to its suitability
|
|
||||||
// for any purpose.
|
|
||||||
//
|
|
||||||
// Revision History:
|
|
||||||
// 11 Feb 2001 Use new iterator_adaptor interface, Fixes for Borland.
|
|
||||||
// (Dave Abrahams)
|
|
||||||
// 04 Feb 2001 Support for user-defined iterator categories (Dave Abrahams)
|
|
||||||
// 30 Jan 2001 Initial Checkin (Dave Abrahams)
|
|
||||||
|
|
||||||
#ifndef BOOST_HALF_OPEN_RANGE_HPP_
|
|
||||||
# define BOOST_HALF_OPEN_RANGE_HPP_
|
|
||||||
|
|
||||||
# include <boost/counting_iterator.hpp>
|
|
||||||
# include <functional>
|
|
||||||
# include <cassert>
|
|
||||||
# include <boost/operators.hpp>
|
|
||||||
# include <string>
|
|
||||||
# include <stdexcept>
|
|
||||||
# include <iterator>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
// Template class choose_finish -- allows us to maintain the invariant that
|
|
||||||
// start() <= finish() on half_open_range specializations that support random
|
|
||||||
// access.
|
|
||||||
#ifdef __MWERKS__
|
|
||||||
template <class T>
|
|
||||||
const T& choose_finish(const T&, const T& finish, std::input_iterator_tag)
|
|
||||||
{
|
|
||||||
return finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
const T& choose_finish(const T&, const T& finish, std::output_iterator_tag)
|
|
||||||
{
|
|
||||||
return finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
const T& choose_finish(const T& start, const T& finish, std::random_access_iterator_tag)
|
|
||||||
{
|
|
||||||
return finish < start ? start : finish;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
template <bool is_random_access> struct finish_chooser;
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct finish_chooser<false>
|
|
||||||
{
|
|
||||||
template <class T>
|
|
||||||
struct rebind
|
|
||||||
{
|
|
||||||
static T choose(const T&, const T& finish)
|
|
||||||
{ return finish; }
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct finish_chooser<true>
|
|
||||||
{
|
|
||||||
template <class T>
|
|
||||||
struct rebind
|
|
||||||
{
|
|
||||||
static T choose(const T& start, const T& finish)
|
|
||||||
{ return finish < start ? start : finish; }
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Category, class Incrementable>
|
|
||||||
struct choose_finish
|
|
||||||
{
|
|
||||||
static const Incrementable choose(const Incrementable& start, const Incrementable& finish)
|
|
||||||
{
|
|
||||||
return finish_chooser<(
|
|
||||||
::boost::is_convertible<Category*,std::random_access_iterator_tag*>::value
|
|
||||||
)>::template rebind<Incrementable>::choose(start, finish);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Incrementable>
|
|
||||||
struct half_open_range
|
|
||||||
{
|
|
||||||
typedef typename counting_iterator_generator<Incrementable>::type iterator;
|
|
||||||
|
|
||||||
private: // utility type definitions
|
|
||||||
// Using iter_t prevents compiler confusion with boost::iterator
|
|
||||||
typedef typename counting_iterator_generator<Incrementable>::type iter_t;
|
|
||||||
|
|
||||||
typedef std::less<Incrementable> less_value;
|
|
||||||
typedef typename iter_t::iterator_category category;
|
|
||||||
typedef half_open_range<Incrementable> self;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef iter_t const_iterator;
|
|
||||||
typedef typename counting_iterator_traits<Incrementable>::value_type value_type;
|
|
||||||
typedef typename counting_iterator_traits<Incrementable>::difference_type difference_type;
|
|
||||||
typedef typename counting_iterator_traits<Incrementable>::reference reference;
|
|
||||||
typedef typename counting_iterator_traits<Incrementable>::reference const_reference;
|
|
||||||
typedef typename counting_iterator_traits<Incrementable>::pointer pointer;
|
|
||||||
typedef typename counting_iterator_traits<Incrementable>::pointer const_pointer;
|
|
||||||
|
|
||||||
// It would be nice to select an unsigned type, but this is appropriate
|
|
||||||
// since the library makes an attempt to select a difference_type which can
|
|
||||||
// hold the difference between any two iterators.
|
|
||||||
typedef typename counting_iterator_traits<Incrementable>::difference_type size_type;
|
|
||||||
|
|
||||||
half_open_range(Incrementable start, Incrementable finish)
|
|
||||||
: m_start(start),
|
|
||||||
m_finish(
|
|
||||||
#ifndef __MWERKS__
|
|
||||||
detail::choose_finish<category,Incrementable>::choose(start, finish)
|
|
||||||
#else
|
|
||||||
detail::choose_finish(start, finish, category())
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{}
|
|
||||||
|
|
||||||
// Implicit conversion from std::pair<Incrementable,Incrementable> allows us
|
|
||||||
// to accept the results of std::equal_range(), for example.
|
|
||||||
half_open_range(const std::pair<Incrementable,Incrementable>& x)
|
|
||||||
: m_start(x.first),
|
|
||||||
m_finish(
|
|
||||||
#ifndef __MWERKS__
|
|
||||||
detail::choose_finish<category,Incrementable>::choose(x.first, x.second)
|
|
||||||
#else
|
|
||||||
detail::choose_finish(x.first, x.second, category())
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{}
|
|
||||||
|
|
||||||
half_open_range& operator=(const self& x)
|
|
||||||
{
|
|
||||||
m_start = x.m_start;
|
|
||||||
m_finish = x.m_finish;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
half_open_range& operator=(const std::pair<Incrementable,Incrementable>& x)
|
|
||||||
{
|
|
||||||
m_start = x.first;
|
|
||||||
m_finish =
|
|
||||||
#ifndef __MWERKS__
|
|
||||||
detail::choose_finish<category,Incrementable>::choose(x.first, x.second);
|
|
||||||
#else
|
|
||||||
detail::choose_finish(x.first, x.second, category();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator begin() const { return iterator(m_start); }
|
|
||||||
iterator end() const { return iterator(m_finish); }
|
|
||||||
|
|
||||||
Incrementable front() const { assert(!this->empty()); return m_start; }
|
|
||||||
Incrementable back() const { assert(!this->empty()); return boost::prior(m_finish); }
|
|
||||||
|
|
||||||
Incrementable start() const { return m_start; }
|
|
||||||
Incrementable finish() const { return m_finish; }
|
|
||||||
|
|
||||||
size_type size() const { return boost::detail::distance(begin(), end()); }
|
|
||||||
|
|
||||||
bool empty() const
|
|
||||||
{
|
|
||||||
return m_finish == m_start;
|
|
||||||
}
|
|
||||||
|
|
||||||
void swap(half_open_range& x) {
|
|
||||||
std::swap(m_start, x.m_start);
|
|
||||||
std::swap(m_finish, x.m_finish);
|
|
||||||
}
|
|
||||||
|
|
||||||
public: // functions requiring random access elements
|
|
||||||
|
|
||||||
// REQUIRES: x is reachable from this->front()
|
|
||||||
bool contains(const value_type& x) const
|
|
||||||
{
|
|
||||||
BOOST_STATIC_ASSERT((boost::is_same<category, std::random_access_iterator_tag>::value));
|
|
||||||
return !less_value()(x, m_start) && less_value()(x, m_finish);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool contains(const half_open_range& x) const
|
|
||||||
{
|
|
||||||
BOOST_STATIC_ASSERT((boost::is_same<category, std::random_access_iterator_tag>::value));
|
|
||||||
return x.empty() || !less_value()(x.m_start, m_start) && !less_value()(m_finish, x.m_finish);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool intersects(const half_open_range& x) const
|
|
||||||
{
|
|
||||||
BOOST_STATIC_ASSERT((boost::is_same<category, std::random_access_iterator_tag>::value));
|
|
||||||
return less_value()(
|
|
||||||
less_value()(this->m_start, x.m_start) ? x.m_start : this->m_start,
|
|
||||||
less_value()(this->m_finish, x.m_finish) ? this->m_finish : x.m_finish);
|
|
||||||
}
|
|
||||||
|
|
||||||
half_open_range& operator&=(const half_open_range& x)
|
|
||||||
{
|
|
||||||
BOOST_STATIC_ASSERT((boost::is_same<category, std::random_access_iterator_tag>::value));
|
|
||||||
|
|
||||||
if (less_value()(this->m_start, x.m_start))
|
|
||||||
this->m_start = x.m_start;
|
|
||||||
|
|
||||||
if (less_value()(x.m_finish, this->m_finish))
|
|
||||||
this->m_finish = x.m_finish;
|
|
||||||
|
|
||||||
if (less_value()(this->m_finish, this->m_start))
|
|
||||||
this->m_start = this->m_finish;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
half_open_range& operator|=(const half_open_range& x)
|
|
||||||
{
|
|
||||||
BOOST_STATIC_ASSERT((boost::is_same<category, std::random_access_iterator_tag>::value));
|
|
||||||
|
|
||||||
if (!x.empty())
|
|
||||||
{
|
|
||||||
if (this->empty())
|
|
||||||
{
|
|
||||||
*this = x;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (less_value()(x.m_start, this->m_start))
|
|
||||||
this->m_start = x.m_start;
|
|
||||||
|
|
||||||
if (less_value()(this->m_finish, x.m_finish))
|
|
||||||
this->m_finish = x.m_finish;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// REQUIRES: x is reachable from this->front()
|
|
||||||
const_iterator find(const value_type& x) const
|
|
||||||
{
|
|
||||||
BOOST_STATIC_ASSERT((boost::is_same<category, std::random_access_iterator_tag>::value));
|
|
||||||
|
|
||||||
return const_iterator(this->contains(x) ? x : m_finish);
|
|
||||||
}
|
|
||||||
|
|
||||||
// REQUIRES: index >= 0 && index < size()
|
|
||||||
value_type operator[](size_type index) const
|
|
||||||
{
|
|
||||||
assert(index >= 0 && index < size());
|
|
||||||
return m_start + index;
|
|
||||||
}
|
|
||||||
|
|
||||||
value_type at(size_type index) const
|
|
||||||
{
|
|
||||||
if (index < 0 || index >= size())
|
|
||||||
throw std::out_of_range(std::string("half_open_range"));
|
|
||||||
return m_start + index;
|
|
||||||
}
|
|
||||||
|
|
||||||
private: // data members
|
|
||||||
Incrementable m_start, m_finish;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Incrementable>
|
|
||||||
half_open_range<Incrementable> operator|(
|
|
||||||
half_open_range<Incrementable> x,
|
|
||||||
const half_open_range<Incrementable>& y)
|
|
||||||
{
|
|
||||||
return x |= y;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Incrementable>
|
|
||||||
half_open_range<Incrementable> operator&(
|
|
||||||
half_open_range<Incrementable> x,
|
|
||||||
const half_open_range<Incrementable>& y)
|
|
||||||
{
|
|
||||||
return x &= y;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Incrementable>
|
|
||||||
inline bool operator==(
|
|
||||||
const half_open_range<Incrementable>& x,
|
|
||||||
const half_open_range<Incrementable>& y)
|
|
||||||
{
|
|
||||||
const bool y_empty = y.empty();
|
|
||||||
return x.empty() ? y_empty : !y_empty && x.start() == y.start() && x.finish() == y.finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Incrementable>
|
|
||||||
inline bool operator!=(
|
|
||||||
const half_open_range<Incrementable>& x,
|
|
||||||
const half_open_range<Incrementable>& y)
|
|
||||||
{
|
|
||||||
return !(x == y);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Incrementable>
|
|
||||||
inline half_open_range<Incrementable>
|
|
||||||
make_half_open_range(Incrementable first, Incrementable last)
|
|
||||||
{
|
|
||||||
return half_open_range<Incrementable>(first, last);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Incrementable>
|
|
||||||
bool intersects(
|
|
||||||
const half_open_range<Incrementable>& x,
|
|
||||||
const half_open_range<Incrementable>& y)
|
|
||||||
{
|
|
||||||
return x.intersects(y);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Incrementable>
|
|
||||||
bool contains(
|
|
||||||
const half_open_range<Incrementable>& x,
|
|
||||||
const half_open_range<Incrementable>& y)
|
|
||||||
{
|
|
||||||
return x.contains(y);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template <class Incrementable> struct less<boost::half_open_range<Incrementable> >
|
|
||||||
: binary_function<
|
|
||||||
boost::half_open_range<Incrementable>,
|
|
||||||
boost::half_open_range<Incrementable>,bool>
|
|
||||||
{
|
|
||||||
bool operator()(
|
|
||||||
const boost::half_open_range<Incrementable>& x,
|
|
||||||
const boost::half_open_range<Incrementable>& y) const
|
|
||||||
{
|
|
||||||
less<Incrementable> cmp;
|
|
||||||
return !y.empty() && (
|
|
||||||
cmp(x.start(), y.start())
|
|
||||||
|| !cmp(y.start(), x.start())
|
|
||||||
&& cmp(x.finish(), y.finish()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Incrementable> struct less_equal<boost::half_open_range<Incrementable> >
|
|
||||||
: binary_function<
|
|
||||||
boost::half_open_range<Incrementable>,
|
|
||||||
boost::half_open_range<Incrementable>,bool>
|
|
||||||
{
|
|
||||||
bool operator()(
|
|
||||||
const boost::half_open_range<Incrementable>& x,
|
|
||||||
const boost::half_open_range<Incrementable>& y) const
|
|
||||||
{
|
|
||||||
typedef boost::half_open_range<Incrementable> range;
|
|
||||||
less<range> cmp;
|
|
||||||
return !cmp(y,x);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template <class Incrementable> struct greater<boost::half_open_range<Incrementable> >
|
|
||||||
: binary_function<
|
|
||||||
boost::half_open_range<Incrementable>,
|
|
||||||
boost::half_open_range<Incrementable>,bool>
|
|
||||||
{
|
|
||||||
bool operator()(
|
|
||||||
const boost::half_open_range<Incrementable>& x,
|
|
||||||
const boost::half_open_range<Incrementable>& y) const
|
|
||||||
{
|
|
||||||
typedef boost::half_open_range<Incrementable> range;
|
|
||||||
less<range> cmp;
|
|
||||||
return cmp(y,x);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Incrementable> struct greater_equal<boost::half_open_range<Incrementable> >
|
|
||||||
: binary_function<
|
|
||||||
boost::half_open_range<Incrementable>,
|
|
||||||
boost::half_open_range<Incrementable>,bool>
|
|
||||||
{
|
|
||||||
bool operator()(
|
|
||||||
const boost::half_open_range<Incrementable>& x,
|
|
||||||
const boost::half_open_range<Incrementable>& y) const
|
|
||||||
{
|
|
||||||
typedef boost::half_open_range<Incrementable> range;
|
|
||||||
less<range> cmp;
|
|
||||||
return !cmp(x,y);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
// Can't partially specialize std::less et al, so we must provide the operators
|
|
||||||
template <class Incrementable>
|
|
||||||
bool operator<(const half_open_range<Incrementable>& x,
|
|
||||||
const half_open_range<Incrementable>& y)
|
|
||||||
{
|
|
||||||
return !y.empty() && (
|
|
||||||
x.empty() || std::less<Incrementable>()(x.start(), y.start())
|
|
||||||
|| !std::less<Incrementable>()(y.start(), x.start())
|
|
||||||
&& std::less<Incrementable>()(x.finish(), y.finish()));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Incrementable>
|
|
||||||
bool operator>(const half_open_range<Incrementable>& x,
|
|
||||||
const half_open_range<Incrementable>& y)
|
|
||||||
{
|
|
||||||
return y < x;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Incrementable>
|
|
||||||
bool operator<=(const half_open_range<Incrementable>& x,
|
|
||||||
const half_open_range<Incrementable>& y)
|
|
||||||
{
|
|
||||||
return !(y < x);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Incrementable>
|
|
||||||
bool operator>=(const half_open_range<Incrementable>& x,
|
|
||||||
const half_open_range<Incrementable>& y)
|
|
||||||
{
|
|
||||||
return !(x < y);
|
|
||||||
}
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif // BOOST_HALF_OPEN_RANGE_HPP_
|
|
@ -1,60 +0,0 @@
|
|||||||
// interator.hpp workarounds for non-conforming standard libraries ---------//
|
|
||||||
|
|
||||||
// (C) Copyright Boost.org 2000. Permission to copy, use, modify, sell and
|
|
||||||
// distribute this software is granted provided this copyright notice appears
|
|
||||||
// in all copies. This software is provided "as is" without express or implied
|
|
||||||
// warranty, and with no claim as to its suitability for any purpose.
|
|
||||||
|
|
||||||
// See http://www.boost.org for most recent version including documentation.
|
|
||||||
|
|
||||||
// Revision History
|
|
||||||
// 12 Jan 01 added <cstddef> for std::ptrdiff_t (Jens Maurer)
|
|
||||||
// 28 Jun 00 Workarounds to deal with known MSVC bugs (David Abrahams)
|
|
||||||
// 26 Jun 00 Initial version (Jeremy Siek)
|
|
||||||
|
|
||||||
#ifndef BOOST_ITERATOR_HPP
|
|
||||||
#define BOOST_ITERATOR_HPP
|
|
||||||
|
|
||||||
#include <iterator>
|
|
||||||
#include <cstddef> // std::ptrdiff_t
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
|
|
||||||
namespace boost
|
|
||||||
{
|
|
||||||
# if defined(BOOST_NO_STD_ITERATOR) && !defined(BOOST_MSVC_STD_ITERATOR)
|
|
||||||
template <class Category, class T,
|
|
||||||
class Distance = std::ptrdiff_t,
|
|
||||||
class Pointer = T*, class Reference = T&>
|
|
||||||
struct iterator
|
|
||||||
{
|
|
||||||
typedef T value_type;
|
|
||||||
typedef Distance difference_type;
|
|
||||||
typedef Pointer pointer;
|
|
||||||
typedef Reference reference;
|
|
||||||
typedef Category iterator_category;
|
|
||||||
};
|
|
||||||
# else
|
|
||||||
|
|
||||||
// declare iterator_base in namespace detail to work around MSVC bugs which
|
|
||||||
// prevent derivation from an identically-named class in a different namespace.
|
|
||||||
namespace detail {
|
|
||||||
template <class Category, class T, class Distance, class Pointer, class Reference>
|
|
||||||
# if !defined(BOOST_MSVC_STD_ITERATOR)
|
|
||||||
struct iterator_base : std::iterator<Category, T, Distance, Pointer, Reference> {};
|
|
||||||
# else
|
|
||||||
struct iterator_base : std::iterator<Category, T, Distance>
|
|
||||||
{
|
|
||||||
typedef Reference reference;
|
|
||||||
typedef Pointer pointer;
|
|
||||||
typedef Distance difference_type;
|
|
||||||
};
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Category, class T, class Distance = std::ptrdiff_t,
|
|
||||||
class Pointer = T*, class Reference = T&>
|
|
||||||
struct iterator : detail::iterator_base<Category, T, Distance, Pointer, Reference> {};
|
|
||||||
# endif
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#endif // BOOST_ITERATOR_HPP
|
|
@ -1,75 +0,0 @@
|
|||||||
// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
|
|
||||||
// sell and distribute this software is granted provided this
|
|
||||||
// copyright notice appears in all copies. This software is provided
|
|
||||||
// "as is" without express or implied warranty, and with no claim as
|
|
||||||
// to its suitability for any purpose.
|
|
||||||
|
|
||||||
#ifndef BOOST_INT_ITERATOR_H
|
|
||||||
#define BOOST_INT_ITERATOR_H
|
|
||||||
|
|
||||||
#include <boost/iterator.hpp>
|
|
||||||
#if !defined BOOST_MSVC
|
|
||||||
#include <boost/operators.hpp>
|
|
||||||
#endif
|
|
||||||
#include <iostream>
|
|
||||||
//using namespace std;
|
|
||||||
|
|
||||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
|
||||||
namespace boost {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// this should use random_access_iterator_helper but I've had
|
|
||||||
// VC++ portablility problems with that. -JGS
|
|
||||||
template <class IntT>
|
|
||||||
class int_iterator
|
|
||||||
{
|
|
||||||
typedef int_iterator self;
|
|
||||||
public:
|
|
||||||
typedef std::random_access_iterator_tag iterator_category;
|
|
||||||
typedef IntT value_type;
|
|
||||||
typedef IntT& reference;
|
|
||||||
typedef IntT* pointer;
|
|
||||||
typedef std::ptrdiff_t difference_type;
|
|
||||||
|
|
||||||
inline int_iterator() : _i(0) { }
|
|
||||||
inline int_iterator(IntT i) : _i(i) { }
|
|
||||||
inline int_iterator(const self& x) : _i(x._i) { }
|
|
||||||
inline self& operator=(const self& x) { _i = x._i; return *this; }
|
|
||||||
inline IntT operator*() { return _i; }
|
|
||||||
inline IntT operator[](IntT n) { return _i + n; }
|
|
||||||
inline self& operator++() { ++_i; return *this; }
|
|
||||||
inline self operator++(int) { self t = *this; ++_i; return t; }
|
|
||||||
inline self& operator+=(IntT n) { _i += n; return *this; }
|
|
||||||
inline self operator+(IntT n) { self t = *this; t += n; return t; }
|
|
||||||
inline self& operator--() { --_i; return *this; }
|
|
||||||
inline self operator--(int) { self t = *this; --_i; return t; }
|
|
||||||
inline self& operator-=(IntT n) { _i -= n; return *this; }
|
|
||||||
inline IntT operator-(const self& x) const { return _i - x._i; }
|
|
||||||
inline bool operator==(const self& x) const { return _i == x._i; }
|
|
||||||
// vc++ had a problem finding != in random_access_iterator_helper
|
|
||||||
// need to look into this... for now implementing everything here -JGS
|
|
||||||
inline bool operator!=(const self& x) const { return _i != x._i; }
|
|
||||||
inline bool operator<(const self& x) const { return _i < x._i; }
|
|
||||||
inline bool operator<=(const self& x) const { return _i <= x._i; }
|
|
||||||
inline bool operator>(const self& x) const { return _i > x._i; }
|
|
||||||
inline bool operator>=(const self& x) const { return _i >= x._i; }
|
|
||||||
protected:
|
|
||||||
IntT _i;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class IntT>
|
|
||||||
inline int_iterator<IntT>
|
|
||||||
operator+(IntT n, int_iterator<IntT> t) { t += n; return t; }
|
|
||||||
|
|
||||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
|
||||||
} /* namespace boost */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef BOOST_NO_OPERATORS_IN_NAMESPACE
|
|
||||||
namespace boost {
|
|
||||||
using ::int_iterator;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* BOOST_INT_ITERATOR_H */
|
|
@ -1,59 +0,0 @@
|
|||||||
// (C) Copyright David Abrahams and Jeremy Siek 2000-2001. Permission to copy,
|
|
||||||
// use, modify, sell and distribute this software is granted provided this
|
|
||||||
// copyright notice appears in all copies. This software is provided "as is"
|
|
||||||
// without express or implied warranty, and with no claim as to its suitability
|
|
||||||
// for any purpose.
|
|
||||||
//
|
|
||||||
// Revision History:
|
|
||||||
// 04 Jan 2001 Factored counting_iterator stuff into
|
|
||||||
// boost/counting_iterator.hpp (David Abrahams)
|
|
||||||
|
|
||||||
#ifndef BOOST_INTEGER_RANGE_HPP_
|
|
||||||
#define BOOST_INTEGER_RANGE_HPP_
|
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
#include <boost/counting_iterator.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
// Counting Iterator and Integer Range Class
|
|
||||||
|
|
||||||
template <class IntegerType>
|
|
||||||
struct integer_range {
|
|
||||||
typedef typename counting_iterator_generator<IntegerType>::type iterator;
|
|
||||||
|
|
||||||
typedef iterator const_iterator;
|
|
||||||
typedef IntegerType value_type;
|
|
||||||
typedef std::ptrdiff_t difference_type;
|
|
||||||
typedef IntegerType reference;
|
|
||||||
typedef IntegerType const_reference;
|
|
||||||
typedef const IntegerType* pointer;
|
|
||||||
typedef const IntegerType* const_pointer;
|
|
||||||
typedef IntegerType size_type;
|
|
||||||
|
|
||||||
integer_range(IntegerType start, IntegerType finish)
|
|
||||||
: m_start(start), m_finish(finish) { }
|
|
||||||
|
|
||||||
iterator begin() const { return iterator(m_start); }
|
|
||||||
iterator end() const { return iterator(m_finish); }
|
|
||||||
size_type size() const { return m_finish - m_start; }
|
|
||||||
bool empty() const { return m_finish == m_start; }
|
|
||||||
void swap(integer_range& x) {
|
|
||||||
std::swap(m_start, x.m_start);
|
|
||||||
std::swap(m_finish, x.m_finish);
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
IntegerType m_start, m_finish;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class IntegerType>
|
|
||||||
inline integer_range<IntegerType>
|
|
||||||
make_integer_range(IntegerType first, IntegerType last)
|
|
||||||
{
|
|
||||||
return integer_range<IntegerType>(first, last);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#endif // BOOST_INTEGER_RANGE_HPP_
|
|
@ -1 +0,0 @@
|
|||||||
#include <boost/iterator_adaptors.hpp>
|
|
@ -1,214 +0,0 @@
|
|||||||
#ifndef BOOST_ITERATOR_TESTS_HPP
|
|
||||||
# define BOOST_ITERATOR_TESTS_HPP
|
|
||||||
|
|
||||||
// This is meant to be the beginnings of a comprehensive, generic
|
|
||||||
// test suite for STL concepts such as iterators and containers.
|
|
||||||
//
|
|
||||||
// Revision History:
|
|
||||||
// 08 Feb 2001 Fixed bidirectional iterator test so that
|
|
||||||
// --i is no longer a precondition.
|
|
||||||
// (Jeremy Siek)
|
|
||||||
// 04 Feb 2001 Added lvalue test, corrected preconditions
|
|
||||||
// (David Abrahams)
|
|
||||||
|
|
||||||
# include <iterator>
|
|
||||||
# include <assert.h>
|
|
||||||
# include <boost/type_traits.hpp>
|
|
||||||
# include <boost/static_assert.hpp>
|
|
||||||
# include <boost/concept_archetype.hpp> // for detail::dummy_constructor
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
// use this for the value type
|
|
||||||
struct dummyT {
|
|
||||||
dummyT() { }
|
|
||||||
dummyT(detail::dummy_constructor) { }
|
|
||||||
dummyT(int x) : m_x(x) { }
|
|
||||||
int foo() const { return m_x; }
|
|
||||||
bool operator==(const dummyT& d) const { return m_x == d.m_x; }
|
|
||||||
int m_x;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Tests whether type Iterator satisfies the requirements for a
|
|
||||||
// TrivialIterator.
|
|
||||||
// Preconditions: i != j, *i == val
|
|
||||||
template <class Iterator, class T>
|
|
||||||
void trivial_iterator_test(const Iterator i, const Iterator j, T val)
|
|
||||||
{
|
|
||||||
Iterator k;
|
|
||||||
assert(i == i);
|
|
||||||
assert(j == j);
|
|
||||||
assert(i != j);
|
|
||||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
|
||||||
T v = *i;
|
|
||||||
#else
|
|
||||||
typename std::iterator_traits<Iterator>::value_type v = *i;
|
|
||||||
#endif
|
|
||||||
assert(v == val);
|
|
||||||
#if 0
|
|
||||||
// hmm, this will give a warning for transform_iterator... perhaps
|
|
||||||
// this should be separated out into a stand-alone test since there
|
|
||||||
// are several situations where it can't be used, like for
|
|
||||||
// integer_range::iterator.
|
|
||||||
assert(v == i->foo());
|
|
||||||
#endif
|
|
||||||
k = i;
|
|
||||||
assert(k == k);
|
|
||||||
assert(k == i);
|
|
||||||
assert(k != j);
|
|
||||||
assert(*k == val);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Preconditions: i != j
|
|
||||||
template <class Iterator, class T>
|
|
||||||
void mutable_trivial_iterator_test(const Iterator i, const Iterator j, T val)
|
|
||||||
{
|
|
||||||
*i = val;
|
|
||||||
trivial_iterator_test(i, j, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Preconditions: *i == v1, *++i == v2
|
|
||||||
template <class Iterator, class T>
|
|
||||||
void input_iterator_test(Iterator i, T v1, T v2)
|
|
||||||
{
|
|
||||||
Iterator i1 = i, i2 = i;
|
|
||||||
|
|
||||||
assert(i == i1++);
|
|
||||||
assert(i != ++i2);
|
|
||||||
|
|
||||||
trivial_iterator_test(i, i1, v1);
|
|
||||||
trivial_iterator_test(i, i2, v1);
|
|
||||||
|
|
||||||
++i;
|
|
||||||
assert(i == i1);
|
|
||||||
assert(i == i2);
|
|
||||||
++i1;
|
|
||||||
++i2;
|
|
||||||
|
|
||||||
trivial_iterator_test(i, i1, v2);
|
|
||||||
trivial_iterator_test(i, i2, v2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// how to test output iterator?
|
|
||||||
|
|
||||||
|
|
||||||
template <bool is_pointer> struct lvalue_test
|
|
||||||
{
|
|
||||||
template <class Iterator> static void check(Iterator)
|
|
||||||
{
|
|
||||||
# ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
|
||||||
typedef typename std::iterator_traits<Iterator>::reference reference;
|
|
||||||
typedef typename std::iterator_traits<Iterator>::value_type value_type;
|
|
||||||
# else
|
|
||||||
typedef typename Iterator::reference reference;
|
|
||||||
typedef typename Iterator::value_type value_type;
|
|
||||||
# endif
|
|
||||||
BOOST_STATIC_ASSERT(boost::is_reference<reference>::value);
|
|
||||||
BOOST_STATIC_ASSERT((boost::is_same<reference,value_type&>::value
|
|
||||||
|| boost::is_same<reference,const value_type&>::value
|
|
||||||
));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
# ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
|
||||||
template <> struct lvalue_test<true> {
|
|
||||||
template <class T> static void check(T) {}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <class Iterator, class T>
|
|
||||||
void forward_iterator_test(Iterator i, T v1, T v2)
|
|
||||||
{
|
|
||||||
input_iterator_test(i, v1, v2);
|
|
||||||
|
|
||||||
// borland doesn't allow non-type template parameters
|
|
||||||
# if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)
|
|
||||||
lvalue_test<(boost::is_pointer<Iterator>::value)>::check(i);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Preconditions: *i == v1, *++i == v2
|
|
||||||
template <class Iterator, class T>
|
|
||||||
void bidirectional_iterator_test(Iterator i, T v1, T v2)
|
|
||||||
{
|
|
||||||
forward_iterator_test(i, v1, v2);
|
|
||||||
++i;
|
|
||||||
|
|
||||||
Iterator i1 = i, i2 = i;
|
|
||||||
|
|
||||||
assert(i == i1--);
|
|
||||||
assert(i != --i2);
|
|
||||||
|
|
||||||
trivial_iterator_test(i, i1, v2);
|
|
||||||
trivial_iterator_test(i, i2, v2);
|
|
||||||
|
|
||||||
--i;
|
|
||||||
assert(i == i1);
|
|
||||||
assert(i == i2);
|
|
||||||
++i1;
|
|
||||||
++i2;
|
|
||||||
|
|
||||||
trivial_iterator_test(i, i1, v1);
|
|
||||||
trivial_iterator_test(i, i2, v1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// mutable_bidirectional_iterator_test
|
|
||||||
|
|
||||||
// Preconditions: [i,i+N) is a valid range
|
|
||||||
template <class Iterator, class TrueVals>
|
|
||||||
void random_access_iterator_test(Iterator i, int N, TrueVals vals)
|
|
||||||
{
|
|
||||||
bidirectional_iterator_test(i, vals[0], vals[1]);
|
|
||||||
const Iterator j = i;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
for (c = 0; c < N-1; ++c) {
|
|
||||||
assert(i == j + c);
|
|
||||||
assert(*i == vals[c]);
|
|
||||||
assert(*i == j[c]);
|
|
||||||
assert(*i == *(j + c));
|
|
||||||
assert(*i == *(c + j));
|
|
||||||
++i;
|
|
||||||
assert(i > j);
|
|
||||||
assert(i >= j);
|
|
||||||
assert(j <= i);
|
|
||||||
assert(j < i);
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator k = j + N - 1;
|
|
||||||
for (c = 0; c < N-1; ++c) {
|
|
||||||
assert(i == k - c);
|
|
||||||
assert(*i == vals[N - 1 - c]);
|
|
||||||
assert(*i == j[N - 1 - c]);
|
|
||||||
Iterator q = k - c;
|
|
||||||
assert(*i == *q);
|
|
||||||
assert(i > j);
|
|
||||||
assert(i >= j);
|
|
||||||
assert(j <= i);
|
|
||||||
assert(j < i);
|
|
||||||
--i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Precondition: i != j
|
|
||||||
template <class Iterator, class ConstIterator>
|
|
||||||
void const_nonconst_iterator_test(Iterator i, ConstIterator j)
|
|
||||||
{
|
|
||||||
assert(i != j);
|
|
||||||
assert(j != i);
|
|
||||||
|
|
||||||
ConstIterator k(i);
|
|
||||||
assert(k == i);
|
|
||||||
assert(i == k);
|
|
||||||
|
|
||||||
k = i;
|
|
||||||
assert(k == i);
|
|
||||||
assert(i == k);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#endif // BOOST_ITERATOR_TESTS_HPP
|
|
Reference in New Issue
Block a user