Compare commits

...

21 Commits

Author SHA1 Message Date
nobody
7963ec54f1 This commit was manufactured by cvs2svn to create tag
'Version_1_25_1'.

[SVN r11623]
2001-11-07 10:35:13 +00:00
Dave Abrahams
75eaa14a18 Removed defunct boost::tied (thanks, Daryle Walker)
[SVN r11622]
2001-11-07 10:35:12 +00:00
Jeremy Siek
082d6e3b32 *** empty log message ***
[SVN r11614]
2001-11-06 16:09:14 +00:00
Jeremy Siek
35b3770b6f *** empty log message ***
[SVN r11613]
2001-11-06 16:05:25 +00:00
Jeremy Siek
5b9d20c7e2 *** empty log message ***
[SVN r11611]
2001-11-06 15:52:56 +00:00
Jeremy Siek
5bbed2372e *** empty log message ***
[SVN r11602]
2001-11-05 21:03:59 +00:00
Jens Maurer
a9d407d239 update SunCC to 6.u2 (C++ 5.3)
[SVN r11601]
2001-11-05 21:00:53 +00:00
Jeremy Siek
3ca4a33a65 updated for named parameters
[SVN r11566]
2001-11-04 16:21:51 +00:00
Jeremy Siek
95197f427c remoeved #if 0
[SVN r11565]
2001-11-04 16:18:10 +00:00
Jeremy Siek
84cdfb032c commit these changes
[SVN r11563]
2001-11-04 04:37:14 +00:00
Dave Abrahams
ec2ceb9c96 no message
[SVN r11508]
2001-11-01 17:22:39 +00:00
John Maddock
6286c893fd Minor regression fixes for Borland and Sunpro tests.
[SVN r11470]
2001-10-30 11:41:35 +00:00
Jeremy Siek
354aef0e8c changed named parameters doc to match new stuff
[SVN r11417]
2001-10-22 17:04:23 +00:00
John Maddock
139e33c36d Updated preprocessor logic to use BOOST_HAS_LONG_LONG
[SVN r11399]
2001-10-18 11:33:52 +00:00
Dave Abrahams
e01de59cdd Made these actually compile
[SVN r11378]
2001-10-12 22:22:42 +00:00
Darin Adler
686f822dea Fix spelling error: "occurances" -> "occurrences".
[SVN r11376]
2001-10-11 17:26:04 +00:00
John Maddock
9961d5c9af Last fix had broken preprocessor logic, now fixed.
[SVN r11373]
2001-10-11 12:04:00 +00:00
John Maddock
628be0d125 Fixes for Sunpro C++ 5.3 (code now works!)
[SVN r11368]
2001-10-09 11:24:56 +00:00
John Maddock
633e45f61a Fixed test to work with sunpro 5.3 (omits array specialisation tests)
[SVN r11359]
2001-10-08 11:35:05 +00:00
John Maddock
2f357c3805 Partial fixes for sunpro 5.3 - doesn't actually work yet though
[SVN r11355]
2001-10-08 11:31:29 +00:00
John Maddock
cda0894d0d Fix for sunpro 5.3 (array specialisations don't work)
[SVN r11354]
2001-10-08 11:30:53 +00:00
14 changed files with 248 additions and 177 deletions

View File

@@ -160,10 +160,10 @@ struct call_traits_checker<T[N]>
//
// check_wrap:
template <class T, class U>
void check_wrap(const contained<T>& w, const U& u)
template <class W, class U>
void check_wrap(const W& w, const U& u)
{
cout << "checking contained<" << typeid(T).name() << ">..." << endl;
cout << "checking " << typeid(W).name() << "..." << endl;
assert(w.value() == u);
}
@@ -211,17 +211,14 @@ int main(int argc, char *argv[ ])
c4(i);
call_traits_checker<const int&> c5;
c5(i);
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__MWERKS__)
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__MWERKS__) && !defined(__SUNPRO_CC)
call_traits_checker<int[2]> c6;
c6(a);
#endif
#endif
check_wrap(wrap(2), 2);
// compiler can't deduce this for some reason:
//const char ca[4] = "abc";
//check_wrap(wrap(ca), ca);
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC)
check_wrap(wrap(a), a);
check_make_pair(test::make_pair(a, a), a, a);
#endif
@@ -376,8 +373,10 @@ void call_traits_test<T, true>::assert_construct(typename boost::call_traits<T>:
unused_variable(v3);
unused_variable(v4);
unused_variable(v5);
#ifndef __BORLANDC__
unused_variable(r2);
unused_variable(cr2);
#endif
unused_variable(cr3);
unused_variable(p2);
unused_variable(p3);
@@ -392,7 +391,7 @@ template struct call_traits_test<int*>;
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)
template struct call_traits_test<int&>;
template struct call_traits_test<const int&>;
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC)
template struct call_traits_test<int[2], true>;
#endif
#endif
@@ -400,7 +399,13 @@ template struct call_traits_test<int[2], true>;
#ifdef BOOST_MSVC
unsigned int expected_failures = 10;
#elif defined(__SUNPRO_CC)
unsigned int expected_failures = 11;
#if(__SUNPRO_CC <= 0x520)
unsigned int expected_failures = 14;
#elif(__SUNPRO_CC <= 0x530)
unsigned int expected_failures = 13;
#else
unsigned int expected_failures = 6;
#endif
#elif defined(__BORLANDC__)
unsigned int expected_failures = 2;
#elif defined(__GNUC__)
@@ -412,3 +417,4 @@ unsigned int expected_failures = 0;

View File

@@ -42,12 +42,13 @@ int main(int, char*[])
// Use indirect iterator to print out numbers by accessing
// them through the array of pointers.
#ifndef BOOST_MSVC
std::cout << "indirectly printing out the numbers from 0 to "
<< N << std::endl;
std::copy(boost::make_indirect_iterator(pointers.begin()),
boost::make_indirect_iterator(pointers.end()),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
#endif
return 0;
}

View File

@@ -109,7 +109,7 @@ struct call_traits<T&const volatile>
typedef T& param_type; // hh removed const
};
#endif
#ifndef __SUNPRO_CC
template <typename T, std::size_t N>
struct call_traits<T [N]>
{
@@ -135,6 +135,7 @@ public:
typedef const array_type& const_reference;
typedef const T* const param_type;
};
#endif
}

View File

@@ -32,6 +32,10 @@
namespace boost
{
template <class T1, class T2>
class compressed_pair;
// compressed_pair
namespace details
@@ -104,10 +108,10 @@ namespace details
compressed_pair_imp(first_param_type x, second_param_type y)
: first_(x), second_(y) {}
explicit compressed_pair_imp(first_param_type x)
compressed_pair_imp(first_param_type x)
: first_(x) {}
explicit compressed_pair_imp(second_param_type y)
compressed_pair_imp(second_param_type y)
: second_(y) {}
first_reference first() {return first_;}
@@ -116,10 +120,10 @@ namespace details
second_reference second() {return second_;}
second_const_reference second() const {return second_;}
void swap(compressed_pair_imp& y)
void swap(::boost::compressed_pair<T1, T2>& y)
{
cp_swap(first_, y.first_);
cp_swap(second_, y.second_);
cp_swap(first_, y.first());
cp_swap(second_, y.second());
}
private:
first_type first_;
@@ -147,10 +151,10 @@ namespace details
compressed_pair_imp(first_param_type x, second_param_type y)
: first_type(x), second_(y) {}
explicit compressed_pair_imp(first_param_type x)
compressed_pair_imp(first_param_type x)
: first_type(x) {}
explicit compressed_pair_imp(second_param_type y)
compressed_pair_imp(second_param_type y)
: second_(y) {}
first_reference first() {return *this;}
@@ -159,10 +163,10 @@ namespace details
second_reference second() {return second_;}
second_const_reference second() const {return second_;}
void swap(compressed_pair_imp& y)
void swap(::boost::compressed_pair<T1,T2>& y)
{
// no need to swap empty base class:
cp_swap(second_, y.second_);
cp_swap(second_, y.second());
}
private:
second_type second_;
@@ -189,10 +193,10 @@ namespace details
compressed_pair_imp(first_param_type x, second_param_type y)
: second_type(y), first_(x) {}
explicit compressed_pair_imp(first_param_type x)
compressed_pair_imp(first_param_type x)
: first_(x) {}
explicit compressed_pair_imp(second_param_type y)
compressed_pair_imp(second_param_type y)
: second_type(y) {}
first_reference first() {return first_;}
@@ -201,10 +205,10 @@ namespace details
second_reference second() {return *this;}
second_const_reference second() const {return *this;}
void swap(compressed_pair_imp& y)
void swap(::boost::compressed_pair<T1,T2>& y)
{
// no need to swap empty base class:
cp_swap(first_, y.first_);
cp_swap(first_, y.first());
}
private:
@@ -233,10 +237,10 @@ namespace details
compressed_pair_imp(first_param_type x, second_param_type y)
: first_type(x), second_type(y) {}
explicit compressed_pair_imp(first_param_type x)
compressed_pair_imp(first_param_type x)
: first_type(x) {}
explicit compressed_pair_imp(second_param_type y)
compressed_pair_imp(second_param_type y)
: second_type(y) {}
first_reference first() {return *this;}
@@ -246,7 +250,7 @@ namespace details
second_const_reference second() const {return *this;}
//
// no need to swap empty bases:
void swap(compressed_pair_imp&) {}
void swap(::boost::compressed_pair<T1,T2>&) {}
};
// JM
@@ -272,7 +276,7 @@ namespace details
compressed_pair_imp(first_param_type x, second_param_type)
: first_type(x) {}
explicit compressed_pair_imp(first_param_type x)
compressed_pair_imp(first_param_type x)
: first_type(x) {}
first_reference first() {return *this;}
@@ -281,7 +285,7 @@ namespace details
second_reference second() {return *this;}
second_const_reference second() const {return *this;}
void swap(compressed_pair_imp&) {}
void swap(::boost::compressed_pair<T1,T2>&) {}
private:
};
@@ -305,7 +309,7 @@ namespace details
compressed_pair_imp(first_param_type x, second_param_type y)
: first_(x), second_(y) {}
explicit compressed_pair_imp(first_param_type x)
compressed_pair_imp(first_param_type x)
: first_(x), second_(x) {}
first_reference first() {return first_;}
@@ -314,10 +318,10 @@ namespace details
second_reference second() {return second_;}
second_const_reference second() const {return second_;}
void swap(compressed_pair_imp<T1, T2, 5>& y)
void swap(::boost::compressed_pair<T1, T2>& y)
{
cp_swap(first_, y.first_);
cp_swap(second_, y.second_);
cp_swap(first_, y.first());
cp_swap(second_, y.second());
}
private:
first_type first_;
@@ -401,7 +405,10 @@ public:
compressed_pair() : base() {}
compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
explicit compressed_pair(first_param_type x) : base(x) {}
#if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530))
explicit
#endif
compressed_pair(first_param_type x) : base(x) {}
first_reference first() {return base::first();}
first_const_reference first() const {return base::first();}
@@ -409,7 +416,7 @@ public:
second_reference second() {return base::second();}
second_const_reference second() const {return base::second();}
void swap(compressed_pair& y) { base::swap(y); }
void swap(::boost::compressed_pair<T,T>& y) { base::swap(y); }
};
template <class T1, class T2>

View File

@@ -26,12 +26,8 @@ template < typename MemberType, int UniqueID = 0 >
class noncopyable;
template < class A, class B >
class tied;
// Also has a few function templates
} // namespace boost

View File

@@ -33,8 +33,8 @@ int main(int, char*[])
char mutable_characters[N];
char* pointers_to_mutable_chars[N];
for (int i = 0; i < N; ++i)
pointers_to_mutable_chars[i] = &mutable_characters[i];
for (int j = 0; j < N; ++j)
pointers_to_mutable_chars[j] = &mutable_characters[j];
PairGen::iterator mutable_indirect_first(pointers_to_mutable_chars),
mutable_indirect_last(pointers_to_mutable_chars + N);
@@ -51,10 +51,12 @@ int main(int, char*[])
// Example of using make_indirect_iterator()
#ifndef BOOST_MSVC
std::copy(boost::make_indirect_iterator(pointers_to_chars),
boost::make_indirect_iterator(pointers_to_chars + N),
std::ostream_iterator<char>(std::cout, ","));
std::cout << std::endl;
#endif
return 0;
}

View File

@@ -4,7 +4,9 @@
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
// 8 Mar 2001 Jeremy Siek
// 04 Nov 2001 Jeremy Siek
// Updated with respect to new named parameter interface.
// 08 Mar 2001 Jeremy Siek
// Initial checkin.
#include <boost/iterator_adaptors.hpp>
@@ -26,9 +28,8 @@ main()
{
typedef boost::iterator_adaptor<my_iter, boost::default_iterator_policies,
boost::iterator_traits_generator
::reference<dummyT>
::iterator_category<std::input_iterator_tag> > iter_type;
boost::reference_is<dummyT>,
boost::iterator_category_is<std::input_iterator_tag> > iter_type;
BOOST_STATIC_ASSERT((boost::is_same<iter_type::iterator_category*,
std::input_iterator_tag*>::value));
@@ -42,12 +43,11 @@ main()
{
typedef boost::iterator_adaptor<dummyT*,
boost::default_iterator_policies,
boost::iterator_traits_generator
::value_type<dummyT>
::reference<const dummyT&>
::pointer<const dummyT*>
::iterator_category<std::forward_iterator_tag>
::difference_type<std::ptrdiff_t> > adaptor_type;
boost::value_type_is<dummyT>,
boost::reference_is<const dummyT&>,
boost::pointer_is<const dummyT*> ,
boost::iterator_category_is<std::forward_iterator_tag>,
boost::difference_type_is<std::ptrdiff_t> > adaptor_type;
adaptor_type i(array);

View File

@@ -7,7 +7,7 @@
#include <functional>
#include <algorithm>
#include <iostream>
#include <boost/pending/iterator_adaptors.hpp>
#include <boost/iterator_adaptors.hpp>
#include <boost/pending/integer_range.hpp>
int
@@ -21,8 +21,7 @@ main(int, char*[])
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
typedef std::binder1st< std::multiplies<int> > Function;
typedef boost::transform_iterator<Function, int*,
boost::iterator<std::random_access_iterator_tag, int>
typedef boost::transform_iterator_generator<Function, int*
>::type doubling_iterator;
doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)),

View File

@@ -9,6 +9,8 @@
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 04 Nov 01 Updated with respect to change in named parameters.
// (Jeremy Siek)
// 08 Mar 01 Moved indirect and transform tests to separate files.
// (Jeremy Siek)
// 19 Feb 01 Take adavantage of improved iterator_traits to do more tests
@@ -52,10 +54,12 @@
#include <boost/pending/iterator_tests.hpp>
#include <boost/pending/integer_range.hpp>
#include <boost/concept_archetype.hpp>
#include <boost/type_traits/same_traits.hpp>
#include <stdlib.h>
#include <vector>
#include <deque>
#include <set>
#include <list>
struct my_iterator_tag : public std::random_access_iterator_tag { };
@@ -97,6 +101,10 @@ typedef std::deque<int> storage;
typedef std::deque<int*> pointer_deque;
typedef std::set<storage::iterator> iterator_set;
template <class T> struct foo;
void blah(int) { }
int
main()
{
@@ -105,17 +113,61 @@ main()
const int N = sizeof(array)/sizeof(dummyT);
// sanity check, if this doesn't pass the test is buggy
boost::random_access_iterator_test(array,N,array);
boost::random_access_iterator_test(array, N, array);
// Check that the policy concept checks and the default policy
// implementation match up.
boost::function_requires<
boost::RandomAccessIteratorPoliciesConcept<
boost::default_iterator_policies, int*,
boost::default_iterator_policies,
boost::iterator_adaptor<int*, boost::default_iterator_policies>,
boost::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t,
int*, int&>
> >();
// Test the named parameters
{
// Test computation of defaults
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies,
boost::value_type_is<int> > Iter1;
// don't use std::iterator_traits here to avoid VC++ problems
BOOST_STATIC_ASSERT((boost::is_same<Iter1::value_type, int>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, int&>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, int*>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::iterator_category, std::random_access_iterator_tag>::value));
}
{
// Test computation of default when the Value is const
typedef boost::iterator_adaptor<std::list<int>::iterator,
boost::default_iterator_policies,
boost::value_type_is<const int> > Iter1;
BOOST_STATIC_ASSERT((boost::is_same<Iter1::value_type, int>::value));
#if defined(__BORLANDC__) || defined(BOOST_MSVC)
// We currently don't know how to workaround this bug.
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, int&>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, int*>::value));
#else
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, const int&>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, const int*>::value));
#endif
}
{
// Test with no defaults
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies,
boost::reference_is<long>,
boost::pointer_is<float*>,
boost::value_type_is<char>,
boost::iterator_category_is<std::input_iterator_tag>,
boost::difference_type_is<int>
> Iter1;
BOOST_STATIC_ASSERT((boost::is_same<Iter1::value_type, char>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, long>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, float*>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::difference_type, int>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::iterator_category, std::input_iterator_tag>::value));
}
// Test the iterator_adaptor
{
boost::iterator_adaptor<dummyT*, boost::default_iterator_policies, dummyT> i(array);
@@ -173,7 +225,7 @@ main()
typedef boost::reverse_iterator_generator<const dummyT*
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
, const dummyT
, dummyT, const dummyT&, const dummyT
#endif
>::type const_reverse_iterator;
@@ -306,12 +358,12 @@ main()
#else
typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
boost::default_iterator_policies,
boost::iterator_traits_generator
::value_type<dummyT>
::reference<const dummyT&>
::pointer<const dummyT*>
::iterator_category<std::forward_iterator_tag>
::difference_type<std::ptrdiff_t> > adaptor_type;
boost::reference_is<const dummyT&>,
boost::pointer_is<const dummyT*> ,
boost::iterator_category_is<std::forward_iterator_tag>,
boost::value_type_is<dummyT>,
boost::difference_type_is<std::ptrdiff_t>
> adaptor_type;
#endif
adaptor_type i(forward_iter);
int zero = 0;

View File

@@ -26,6 +26,37 @@
"../../more/generic_programming.html#adaptors">adaptors</a> which apply
specific useful behaviors to arbitrary base iterators.
<h2>Backward Compatibility Note</h2>
<p>The library's interface has changed since it was first released, breaking
backward compatibility:
<ol>
<li><a href="#policies">Policies classes</a> now operate on instances of the
whole <tt>iterator_adaptor</tt> object, rather than just operating on the
<tt>Base</tt> object. This change not only gives the policies class access
to both members of a pair of interacting iterators, but also eliminates the
need for the ugly <tt>type&lt;Reference&gt;</tt> and
<tt>type&lt;Difference&gt;</tt> parameters to various policy functions.
<li>The <a href="#named_template_parameters">Named Template Parameter</a>
interface has been made simpler, easier to use, and compatible with more
compilers.
</ol>
<h2>Other Documentation</h2>
<p><a href="iterator_adaptors.pdf">``Policy Adaptors and the Boost Iterator
Adaptor Library''</a> is a technical paper describing this library and the
powerful design pattern on which it is based. It was presented at the <a
href="http://www.oonumerics.org/tmpw01">C++ Template Workshop</a> at OOPSLA
2001; the slides from the talk are available <a
href="iterator_adaptors.ppt">here</a>. Please note that while the slides
incorporate the minor interface changes described in the previous section,
the paper does not.
<h2>Table of Contents</h2>
<ul>
@@ -131,11 +162,11 @@
<p><tt>iterator_adaptor</tt> is declared like this:
<pre>
template &lt;class Base, class Policies,
class ValueOrNamedParams = typename std::iterator_traits&lt;Base&gt;::value_type,
class ReferenceOrNamedParams = <i>...(see below)</i>,
class PointerOrNamedParams = <i>...(see below)</i>,
class CategoryOrNamedParams = typename std::iterator_traits&lt;Base&gt;::iterator_category,
class DistanceOrNamedParams = typename std::iterator_traits&lt;Base&gt;::difference_type&gt;
class ValueOrNamedParam = typename std::iterator_traits&lt;Base&gt;::value_type,
class ReferenceOrNamedParam = <i>...(see below)</i>,
class PointerOrNamedParam = <i>...(see below)</i>,
class CategoryOrNamedParam = typename std::iterator_traits&lt;Base&gt;::iterator_category,
class DistanceOrNamedParam = typename std::iterator_traits&lt;Base&gt;::difference_type&gt;
struct iterator_adaptor;
</pre>
@@ -183,7 +214,7 @@ struct iterator_adaptor;
particular, the result type of <tt>operator*()</tt>.<br>
<b>Default:</b> If <tt>Value</tt> is supplied, <tt>Value&amp;</tt> is
used. Otherwise
<tt>std::iterator_traits&lt;BaseType&gt;::reference</tt> is used.
<tt>std::iterator_traits&lt;BaseType&gt;::reference</tt> is used. <a href="#7">[7]</a>
<tr>
<td><tt>Pointer</tt>
@@ -191,7 +222,7 @@ struct iterator_adaptor;
<td>The <tt>pointer</tt> type of the resulting iterator, and in
particular, the result type of <tt>operator-&gt;()</tt>.<br>
<b>Default:</b> If <tt>Value</tt> was supplied, then <tt>Value*</tt>,
otherwise <tt>std::iterator_traits&lt;BaseType&gt;::pointer</tt>.
otherwise <tt>std::iterator_traits&lt;BaseType&gt;::pointer</tt>. <a href="#7">[7]</a>
<tr>
<td><tt>Category</tt>
@@ -208,11 +239,9 @@ struct iterator_adaptor;
<tt>std::iterator_traits&lt;BaseType&gt;::difference_type</tt>
<tr>
<td><tt>NamedParams</tt>
<td><tt>NamedParam</tt>
<td>A list of named template parameters generated using the
<a href="#iterator_traits_generator">
<tt>iterator_traits_generator</tt></a> class (see below).
<td>A named template parameter (see below).
</table>
<h3><a name="named_template_parameters">Named Template Parameters</a></h3>
@@ -223,59 +252,32 @@ struct iterator_adaptor;
template parameter, but use the defaults for the third through
fifth. As a solution to these problems we provide a mechanism for
naming the last five template parameters, and providing them in
any order through the <tt>iterator_traits_generator</tt> class.
any order through a set of named template parameters. The following
classes are provided for specifying the parameters. Any of these
classes can be used for any of the last five template parameters
of <tt>iterator_adaptor</tt>.
<blockquote>
<pre>
<a name="iterator_traits_generator">class iterator_traits_generator</a>
{
public:
template &lt;class Value&gt;
struct value_type : public <i>recursive magic</i> { };
template &lt;class Reference&gt;
struct reference : public <i>recursive magic</i> { };
template &lt;class Pointer&gt;
struct pointer : public <i>recursive magic</i> { };
template &lt;class Distance&gt;
struct difference_type : public <i>recursive magic</i> { };
template &lt;class Category&gt;
struct iterator_category : public <i>recursive magic</i> { };
};
template &lt;class Value&gt; struct value_type_is;
template &lt;class Reference&gt; struct reference_is;
template &lt;class Pointer&gt; struct pointer_is;
template &lt;class Distance&gt; struct difference_type_is;
template &lt;class Category&gt; struct iterator_category_is;
</pre>
</blockquote>
The <tt>iterator_traits_generator</tt> is used to create a list of
of template arguments. For example, suppose you want to set the
<tt>Reference</tt> and <tt>Category</tt> parameters, and use the
defaults for the rest. Then you can use the traits generator as
follows:
For example, the following adapts <tt>foo_iterator</tt> to create
an <a href=
"http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>
with <tt>reference</tt> type <tt>foo</tt>, and whose other traits
are determined according to the defaults described <a
href="#template_parameters">above</a>.
<blockquote>
<pre>
iterator_traits_generator::reference&lt;foo&gt;::category&lt;std::input_iterator_tag&gt;
</pre>
</blockquote>
This generated type can then be passed into the <tt>iterator_adaptor</tt>
class to replace any of the last five parameters. If you use the traits
generator in the <i>i</i>th parameter position, then the parameters <i>i</i>
through 7 will use the types specified in the generator. For example, the
following adapts <tt>foo_iterator</tt> to create an <a href=
"http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a> with
<tt>reference</tt> type <tt>foo</tt>, and whose other traits are determined
according to the defaults described <a href="#template_parameters">above</a>.
<blockquote>
<pre>
iterator_adaptor&lt;foo_iterator, foo_policies,
iterator_traits_generator
::reference&lt;foo&gt;
::iterator_category&lt;std::input_iterator_tag&gt;
&gt;
typedef iterator_adaptor&lt;foo_iterator, foo_policies,
reference_is&lt;foo&gt;, iterator_category_is&lt;std::input_iterator_tag&gt;
&gt; MyIterator;
</pre>
</blockquote>
@@ -414,40 +416,40 @@ iterator_adaptor&lt;foo_iterator, foo_policies,
<pre>
struct <a name="default_iterator_policies">default_iterator_policies</a>
{
template &lt;class BaseType&gt;
void initialize(BaseType&amp;)
{ }
// Some of these members were defined static, but Borland got confused
// and thought they were non-const. Also, Sun C++ does not like static
// function templates.
template &lt;class Reference, class BaseType&gt;
Reference dereference(type&lt;Reference&gt;, const BaseType&amp; x) const
{ return *x; }
template &lt;class Base&gt;
void initialize(Base&amp;)
{ }
template &lt;class BaseType&gt;
void increment(BaseType&amp; x)
{ ++x; }
template &lt;class IteratorAdaptor&gt;
typename IteratorAdaptor::reference dereference(const IteratorAdaptor&amp; x) const
{ return *x.base(); }
template &lt;class BaseType1, class BaseType2&gt;
bool equal(const BaseType1&amp; x, const BaseType2&amp; y) const
{ return x == y; }
template &lt;class IteratorAdaptor&gt;
void increment(IteratorAdaptor&amp; x)
{ ++x.base(); }
template &lt;class BaseType&gt;
void decrement(BaseType&amp; x)
{ --x; }
template &lt;class IteratorAdaptor&gt;
void decrement(IteratorAdaptor&amp; x)
{ --x.base(); }
template &lt;class BaseType, class DifferenceType&gt;
void advance(BaseType&amp; x, DifferenceType n)
{ x += n; }
template &lt;class IteratorAdaptor, class DifferenceType&gt;
void advance(IteratorAdaptor&amp; x, DifferenceType n)
{ x.base() += n; }
template &lt;class Difference, class BaseType1, class BaseType2&gt;
Difference distance(type&lt;Difference&gt;, const BaseType1&amp; x, const BaseType2&amp; y) const
{ return y - x; }
template &lt;class IteratorAdaptor1, class IteratorAdaptor2&gt;
typename IteratorAdaptor1::difference_type
distance(const IteratorAdaptor1&amp; x, const IteratorAdaptor2&amp; y) const
{ return y.base() - x.base(); }
template &lt;class BaseType1, class BaseType2&gt;
bool less(const BaseType1&amp; x, const BaseType2&amp; y) const
{ return x &lt; y; }
template &lt;class IteratorAdaptor1, class IteratorAdaptor2&gt;
bool equal(const IteratorAdaptor1&amp; x, const IteratorAdaptor2&amp; y) const
{ return x.base() == y.base(); }
};
</pre>
</blockquote>
</pre></blockquote>
<p>Template member functions are used throughout
<tt>default_iterator_policies</tt> so that it can be employed with a wide
@@ -480,7 +482,7 @@ struct <a name="default_iterator_policies">default_iterator_policies</a>
iterator_adaptor(const
iterator_adaptor&lt;B,Policies,V,R,P,Category,Distance&gt;&amp;)</tt>
<br><br>
This constructor allows for conversion from non-<tt>const</tt> to
This constructor allows for conversion from mutable to
constant adapted iterators. See <a href=
"#iterator_interactions">below</a> for more details.<br>
Requires: <tt>B</tt> is convertible to <tt>Base</tt>.
@@ -512,34 +514,31 @@ struct <a name="default_iterator_policies">default_iterator_policies</a>
<p>To implement a transform iterator we will only change one of the base
iterator's behaviors, so the <tt>transform_iterator_policies</tt> class can
inherit the rest from <tt>default_iterator_policies</tt>. We will define
the <tt>dereference()</tt> member function, which is used to implement
inherit the rest from <tt>default_iterator_policies</tt>. We will define the
<tt>dereference()</tt> member function, which is used to implement
<tt>operator*()</tt> of the adapted iterator. The implementation will
dereference the base iterator and apply the function object. The
<tt>type&lt;Reference&gt;</tt> parameter is used to convey the appropriate
return type. The complete code for <tt>transform_iterator_policies</tt>
is:<br>
dereference the base iterator and apply the function object. The complete
code for <tt>transform_iterator_policies</tt> is:<br>
<br>
<blockquote>
<pre>
template &lt;class AdaptableUnaryFunction&gt;
struct transform_iterator_policies : public default_iterator_policies
{
<blockquote><pre>
template &lt;class AdaptableUnaryFunction&gt;
struct transform_iterator_policies : public default_iterator_policies
{
transform_iterator_policies() { }
transform_iterator_policies(const AdaptableUnaryFunction&amp; f)
: m_f(f) { }
template &lt;class Reference, class BaseIterator&gt;
Reference dereference(type&lt;Reference&gt;, const BaseIterator&amp; i) const
{ return m_f(*i); }
: m_f(f) { }
template &lt;class IteratorAdaptor&gt;
typename IteratorAdaptor::reference
dereference(const IteratorAdaptor&amp; iter) const
{ return m_f(*iter.base()); }
AdaptableUnaryFunction m_f;
};
</pre>
</blockquote>
};
</pre></blockquote>
<p>The next step is to use the <tt>iterator_adaptor</tt> template to
construct the transform iterator type. The nicest way to package the
@@ -575,7 +574,7 @@ public:
<p>As a finishing touch, we will create an <a href=
"../../more/generic_programming.html#object_generator">object generator</a>
for the transform iterator. This is a function that makes it more
for the transform iterator. Our object generator makes it more
convenient to create a transform iterator.<br>
<br>
@@ -814,12 +813,12 @@ bool operator==(const iterator_adaptor&lt;B1,P,V1,R1,P1,C,D&gt;&amp;,
<tt>reference</tt> types for all <a href=
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterators</a> are
<tt>const T*</tt> and <tt>const T&amp;</tt>, respectively. Stripping the
<tt>const</tt>-ness of <tt>Value</tt> allows you to easily
make a <tt>const</tt> iterator adaptor by supplying a <tt>const</tt> type
for <tt>Value</tt>, and allowing the defaults for the <tt>Pointer</tt> and
<tt>Reference</tt> parameters to take effect. Although compilers that don't
support partial specialization won't strip <tt>const</tt> for you, having a
<tt>const value_type</tt> is often harmless in practice.
<tt>const</tt>-ness of <tt>Value</tt> allows you to easily make a constant
iterator by supplying a <tt>const</tt> type for <tt>Value</tt>, and allowing
the defaults for the <tt>Pointer</tt> and <tt>Reference</tt> parameters to
take effect. Although compilers that don't support partial specialization
won't strip <tt>const</tt> for you, having a <tt>const value_type</tt> is
often harmless in practice.
<p><a name="2">[2]</a> If your compiler does not support partial
specialization and the base iterator is a builtin pointer type, you
@@ -885,6 +884,14 @@ bool operator==(const iterator_adaptor&lt;B1,P,V1,R1,P1,C,D&gt;&amp;,
*x = i;
</pre>
<p><a name="7">[7]</a>
If you are using a compiler that does not have a version of
<tt>std::iterator_traits</tt> that works for pointers (i.e., if your
compiler does not support partial specialization) then if the
<tt>Base</tt> type is a const pointer, then the correct defaults
for the <tt>reference</tt> and <tt>pointer</tt> types can not be
deduced. You must specify these types explicitly.
<hr>
<p>Revised

BIN
iterator_adaptors.pdf Normal file

Binary file not shown.

BIN
iterator_adaptors.ppt Normal file

Binary file not shown.

View File

@@ -374,7 +374,7 @@ int main()
test<unsigned int>();
test<long>();
test<unsigned long>();
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
#if defined(BOOST_HAS_LONG_LONG) && !defined(BOOST_NO_INTEGRAL_INT64_T)
test<long long>();
test<unsigned long long>();
#elif defined(BOOST_MSVC)

View File

@@ -14,7 +14,7 @@
//
// 3 successfully inserted.
// 9 was already in the set.
// There were 2 occurances of 4.
// There were 2 occurrences of 4.
#include <set>
#include <algorithm>
@@ -55,7 +55,7 @@ main(int, char*[])
boost::tie(i,end) = std::equal_range(vals, vals + 6, 4);
std::cout << "There were " << std::distance(i,end)
<< " occurances of " << *i << "." << std::endl;
<< " occurrences of " << *i << "." << std::endl;
// Footnote: of course one would normally just use std::count()
// to get this information, but that would spoil the example :)
}