Compare commits

..

1 Commits

Author SHA1 Message Date
nobody
de139ac75e This commit was manufactured by cvs2svn to create tag
'Version_1_18_2'.

[SVN r8120]
2000-11-03 20:02:18 +00:00
13 changed files with 368 additions and 688 deletions

View File

@@ -170,28 +170,6 @@ denotes the address of <tt>u</tt>
<LI><tt>std::pair</tt>
</UL>
<h3>Concept Checking Class</h3>
<pre>
template &lt;class T&gt;
struct CopyConstructibleConcept
{
void constraints() {
T a(b); // require copy constructor
T* ptr = &amp;a; // require address of operator
const_constraints(a);
ignore_unused_variable_warning(ptr);
}
void const_constraints(const T&amp; a) {
T c(a); // require const copy constructor
const T* ptr = &amp;a; // require const address of operator
ignore_unused_variable_warning(c);
ignore_unused_variable_warning(ptr);
}
T b;
};
</pre>
<h3>See also</h3>
<A
href="http://www.sgi.com/Technology/STL/DefaultConstructible.html">DefaultConstructible</A>

View File

@@ -1,212 +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. 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) 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>LessThanComparable</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">
<!--end header-->
<BR Clear>
<H1>LessThanComparable</H1>
<h3>Description</h3>
A type is LessThanComparable if it is ordered: it must
be possible to compare two objects of that type using <tt>operator&lt;</tt>, and
<tt>operator&lt;</tt> must be a strict weak ordering relation.
<h3>Refinement of</h3>
<h3>Associated types</h3>
<h3>Notation</h3>
<Table>
<TR>
<TD VAlign=top>
<tt>X</tt>
</TD>
<TD VAlign=top>
A type that is a model of LessThanComparable
</TD>
</TR>
<TR>
<TD VAlign=top>
<tt>x</tt>, <tt>y</tt>, <tt>z</tt>
</TD>
<TD VAlign=top>
Object of type <tt>X</tt>
</TD>
</tr>
</table>
<h3>Definitions</h3>
Consider the relation <tt>!(x &lt; y) &amp;&amp; !(y &lt; x)</tt>. If this relation is
transitive (that is, if <tt>!(x &lt; y) &amp;&amp; !(y &lt; x) &amp;&amp; !(y &lt; z) &amp;&amp; !(z &lt; y)</tt>
implies <tt>!(x &lt; z) &amp;&amp; !(z &lt; x)</tt>), then it satisfies the mathematical
definition of an equivalence relation. In this case, <tt>operator&lt;</tt>
is a <i>strict weak ordering</i>.
<P>
If <tt>operator&lt;</tt> is a strict weak ordering, and if each equivalence class
has only a single element, then <tt>operator&lt;</tt> is a <i>total ordering</i>.
<h3>Valid expressions</h3>
<Table border>
<TR>
<TH>
Name
</TH>
<TH>
Expression
</TH>
<TH>
Type requirements
</TH>
<TH>
Return type
</TH>
</TR>
<TR>
<TD VAlign=top>
Less
</TD>
<TD VAlign=top>
<tt>x &lt; y</tt>
</TD>
<TD VAlign=top>
&nbsp;
</TD>
<TD VAlign=top>
Convertible to <tt>bool</tt>
</TD>
</TR>
</table>
<h3>Expression semantics</h3>
<Table border>
<TR>
<TH>
Name
</TH>
<TH>
Expression
</TH>
<TH>
Precondition
</TH>
<TH>
Semantics
</TH>
<TH>
Postcondition
</TH>
</TR>
<TR>
<TD VAlign=top>
Less
</TD>
<TD VAlign=top>
<tt>x &lt; y</tt>
</TD>
<TD VAlign=top>
<tt>x</tt> and <tt>y</tt> are in the domain of <tt>&lt;</tt>
</TD>
<TD VAlign=top>
&nbsp;
</TD>
</table>
<h3>Complexity guarantees</h3>
<h3>Invariants</h3>
<Table border>
<TR>
<TD VAlign=top>
Irreflexivity
</TD>
<TD VAlign=top>
<tt>x &lt; x</tt> must be false.
</TD>
</TR>
<TR>
<TD VAlign=top>
Antisymmetry
</TD>
<TD VAlign=top>
<tt>x &lt; y</tt> implies !(y &lt; x) <A href="#2">[2]</A>
</TD>
</TR>
<TR>
<TD VAlign=top>
Transitivity
</TD>
<TD VAlign=top>
<tt>x &lt; y</tt> and <tt>y &lt; z</tt> implies <tt>x &lt; z</tt> <A href="#3">[3]</A>
</TD>
</tr>
</table>
<h3>Models</h3>
<UL>
<LI>
int
</UL>
<h3>Notes</h3>
<P><A name="1">[1]</A>
Only <tt>operator&lt;</tt> is fundamental; the other inequality operators
are essentially syntactic sugar.
<P><A name="2">[2]</A>
Antisymmetry is a theorem, not an axiom: it follows from
irreflexivity and transitivity.
<P><A name="3">[3]</A>
Because of irreflexivity and transitivity, <tt>operator&lt;</tt> always
satisfies the definition of a <i>partial ordering</i>. The definition of
a <i>strict weak ordering</i> is stricter, and the definition of a
<i>total ordering</i> is stricter still.
<h3>See also</h3>
<A href="http://www.sgi.com/Technology/STL/EqualityComparable.html">EqualityComparable</A>, <A href="http://www.sgi.com/Technology/STL/StrictWeakOrdering.html">StrictWeakOrdering</A>
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF=http://www.lsc.nd.edu/~jsiek>Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
</TD></TR></TABLE>
</BODY>
</HTML>

148
cast.htm Normal file
View File

@@ -0,0 +1,148 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Header boost/cast.hpp Documentation</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Header
<a href="../../boost/cast.hpp">boost/cast.hpp</a></h1>
<h2><a name="Cast Functions">Cast Functions</a></h2>
<p>The <code>header <a href="../../boost/cast.hpp">boost/cast.hpp</a></code>
provides <a href="#Polymorphic_cast"><b>polymorphic_cast</b></a>, <a href="#Polymorphic_cast"><b>polymorphic_downcast</b></a>,
and <a href="#numeric_cast"><b>numeric_cast</b></a> template functions designed
to complement the C++ Standard's built-in casts.</p>
<p>The program&nbsp;<a href="cast_test.cpp">cast_test.cpp</a> can be used to
verify these function templates work as expected.</p>
<p><b>polymorphic_cast</b> was suggested by Bjarne Stroustrup in &quot;The C++
Programming Language&quot;.<br>
<b>polymorphic_downcast</b> was contributed by <a href="../../people/dave_abrahams.htm">Dave
Abrahams</a>.<b><br>
numeric_cast</b> was contributed by <a href="../../people/kevlin_henney.htm">Kevlin
Henney</a>.</p>
<h3>Namespace synopsis</h3>
<blockquote>
<pre>namespace boost {
namespace cast {
// all synopsis below included here
}
using ::boost::cast::polymorphic_cast;
using ::boost::cast::polymorphic_downcast;
using ::boost::cast::bad_numeric_cast;
using ::boost::cast::numeric_cast;
}</pre>
</blockquote>
<h3><a name="Polymorphic_cast">Polymorphic casts</a></h3>
<p>Pointers to polymorphic objects (objects of classes which define at least one
virtual function) are sometimes downcast or crosscast.&nbsp; Downcasting means
casting from a base class to a derived class.&nbsp; Crosscasting means casting
across an inheritance hierarchy diagram, such as from one base to the other in a
<b>Y</b> diagram hierarchy.</p>
<p>Such casts can be done with old-style casts, but this approach is never to be
recommended.&nbsp; Old-style casts are sorely lacking in type safety, suffer
poor readability, and are difficult to locate with search tools.</p>
<p>The C++ built-in <b>static_cast</b> can be used for efficiently downcasting
pointers to polymorphic objects, but provides no error detection for the case
where the pointer being cast actually points to the wrong derived class. The <b>polymorphic_downcast</b>
template retains the efficiency of <b>static_cast</b> for non-debug
compilations, but for debug compilations adds safety via an assert() that a <b>dynamic_cast</b>
succeeds.&nbsp;<b>&nbsp;</b></p>
<p>The C++ built-in <b>dynamic_cast</b> can be used for downcasts and crosscasts
of pointers to polymorphic objects, but error notification in the form of a
returned value of 0 is inconvenient to test, or worse yet, easy to forget to
test.&nbsp; The <b>polymorphic_cast</b> template performs a <b>dynamic_cast</b>,
and throws an exception if the <b>dynamic_cast</b> returns 0.</p>
<p>A <b>polymorphic_downcast</b> is preferred when debug-mode tests will cover
100% of the object types possibly cast and when non-debug-mode efficiency is an
issue. If these two conditions are not present, <b>polymorphic_cast</b> is
preferred.&nbsp; It must also be used for crosscasts.&nbsp; It does an assert(
dynamic_cast&lt;Derived&gt;(x) == x ) where x is the base pointer, ensuring that
not only is a non-zero pointer returned, but also that it correct in the
presence of multiple inheritance. .<b> Warning:</b>: Because <b>polymorphic_downcast</b>
uses assert(), it violates the One Definition Rule if NDEBUG is inconsistently
defined across translation units.</p>
<p>The C++ built-in <b>dynamic_cast</b> must be used to cast references rather
than pointers.&nbsp; It is also the only cast that can be used to check whether
a given interface is supported; in that case a return of 0 isn't an error
condition.</p>
<h3>polymorphic_cast and polymorphic_downcast synopsis</h3>
<blockquote>
<pre>template &lt;class Derived, class Base&gt;
inline Derived polymorphic_cast(Base* x);
// Throws: std::bad_cast if ( dynamic_cast&lt;Derived&gt;(x) == 0 )
// Returns: dynamic_cast&lt;Derived&gt;(x)
template &lt;class Derived, class Base&gt;
inline Derived polymorphic_downcast(Base* x);
// Effects: assert( dynamic_cast&lt;Derived&gt;(x) == x );
// Returns: static_cast&lt;Derived&gt;(x)</pre>
</blockquote>
<h3>polymorphic_downcast example</h3>
<blockquote>
<pre>#include &lt;boost/cast.hpp&gt;
...
class Fruit { public: virtual ~Fruit(){}; ... };
class Banana : public Fruit { ... };
...
void f( Fruit * fruit ) {
// ... logic which leads us to believe it is a Banana
Banana * banana = boost::polymorphic_downcast&lt;Banana*&gt;(fruit);
...</pre>
</blockquote>
<h3><a name="numeric_cast">numeric_cast</a></h3>
<p>A <b>static_cast</b>, <b>implicit_cast</b> or implicit conversion will not
detect failure to preserve range for numeric casts. The <b>numeric_cast</b>
template function are similar to <b>static_cast</b> and certain (dubious)
implicit conversions in this respect, except that they detect loss of numeric
range. An exception is thrown when a runtime value preservation check fails.</p>
<p>The requirements on the argument and result types are:</p>
<blockquote>
<ul>
<li>Both argument and result types are CopyConstructible [20.1.3].</li>
<li>Both argument and result types are Numeric, defined by <code>std::numeric_limits&lt;&gt;::is_specialized</code>
being true.</li>
<li>The argument can be converted to the result type using <b>static_cast</b>.</li>
</ul>
</blockquote>
<h3>numeric_cast synopsis</h3>
<blockquote>
<pre>class bad_numeric_cast : public std::bad_cast {...};
template&lt;typename Target, typename Source&gt;
inline Target numeric_cast(Source arg);
// Throws: bad_numeric_cast unless, in converting arg from Source to Target,
// there is no loss of negative range, and no underflow, and no
// overflow, as determined by std::numeric_limits
// Returns: static_cast&lt;Target&gt;(arg)</pre>
</blockquote>
<h3>numeric_cast example</h3>
<blockquote>
<pre>#include &lt;boost/cast.hpp&gt;
using namespace boost::cast;
void ariane(double vx)
{
...
unsigned short dx = numeric_cast&lt;unsigned short&gt;(vx);
...
}</pre>
</blockquote>
<h3>numeric_cast rationale</h3>
<p>The form of the throws condition is specified so that != is not a required
operation.</p>
<hr>
<p>Revised&nbsp; <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan
-->28 June, 2000<!--webbot bot="Timestamp" endspan i-checksum="19846"
--></p>
<p><EFBFBD> Copyright boost.org 1999. Permission to copy, use, modify, sell and
distribute this document is granted provided this copyright notice appears in
all copies. This document is provided &quot;as is&quot; without express or
implied warranty, and with no claim as to its suitability for any purpose.</p>
</body>
</html>

153
cast_test.cpp Normal file
View File

@@ -0,0 +1,153 @@
// boost utility cast test program -----------------------------------------//
// (C) Copyright boost.org 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.
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 28 Jun 00 implicit_cast removed (Beman Dawes)
// 30 Aug 99 value_cast replaced by numeric_cast
// 3 Aug 99 Initial Version
#include <iostream>
#include <climits>
#include <limits>
#include <boost/cast.hpp>
# if SCHAR_MAX == LONG_MAX
# error "This test program doesn't work if SCHAR_MAX == LONG_MAX"
# endif
using namespace boost;
using std::cout;
namespace
{
struct Base
{
virtual char kind() { return 'B'; }
};
struct Base2
{
virtual char kind2() { return '2'; }
};
struct Derived : public Base, Base2
{
virtual char kind() { return 'D'; }
};
}
int main( int argc, char * argv[] )
{
cout << "Usage: test_casts [n], where n omitted or is:\n"
" 1 = execute #1 assert failure (#ifndef NDEBUG)\n"
" 2 = execute #2 assert failure (#ifndef NDEBUG)\n"
"Example: test_casts 2\n\n";
# ifdef NDEBUG
cout << "NDEBUG is defined\n";
# else
cout << "NDEBUG is not defined\n";
# endif
cout << "\nBeginning tests...\n";
// test polymorphic_cast ---------------------------------------------------//
// tests which should succeed
Base * base = new Derived;
Base2 * base2 = 0;
Derived * derived = 0;
derived = polymorphic_downcast<Derived*>( base ); // downcast
assert( derived->kind() == 'D' );
derived = 0;
derived = polymorphic_cast<Derived*>( base ); // downcast, throw on error
assert( derived->kind() == 'D' );
base2 = polymorphic_cast<Base2*>( base ); // crosscast
assert( base2->kind2() == '2' );
// tests which should result in errors being detected
int err_count = 0;
base = new Base;
if ( argc > 1 && *argv[1] == '1' )
{ derived = polymorphic_downcast<Derived*>( base ); } // #1 assert failure
bool caught_exception = false;
try { derived = polymorphic_cast<Derived*>( base ); }
catch (std::bad_cast)
{ cout<<"caught bad_cast\n"; caught_exception = true; }
if ( !caught_exception ) ++err_count;
// the following is just so generated code can be inspected
if ( derived->kind() == 'B' ) ++err_count;
// test implicit_cast and numeric_cast -------------------------------------//
// tests which should succeed
long small_value = 1;
long small_negative_value = -1;
long large_value = std::numeric_limits<long>::max();
long large_negative_value = std::numeric_limits<long>::min();
signed char c = 0;
c = large_value; // see if compiler generates warning
c = numeric_cast<signed char>( small_value );
assert( c == 1 );
c = 0;
c = numeric_cast<signed char>( small_value );
assert( c == 1 );
c = 0;
c = numeric_cast<signed char>( small_negative_value );
assert( c == -1 );
// These tests courtesy of Joe R NWP Swatosh<joe.r.swatosh@usace.army.mil>
assert( 0.0f == numeric_cast<float>( 0.0 ) );
assert( 0.0 == numeric_cast<double>( 0.0 ) );
// tests which should result in errors being detected
caught_exception = false;
try { c = numeric_cast<signed char>( large_value ); }
catch (bad_numeric_cast)
{ cout<<"caught bad_numeric_cast #1\n"; caught_exception = true; }
if ( !caught_exception ) ++err_count;
caught_exception = false;
try { c = numeric_cast<signed char>( large_negative_value ); }
catch (bad_numeric_cast)
{ cout<<"caught bad_numeric_cast #2\n"; caught_exception = true; }
if ( !caught_exception ) ++err_count;
unsigned long ul;
caught_exception = false;
try { ul = numeric_cast<unsigned long>( large_negative_value ); }
catch (bad_numeric_cast)
{ cout<<"caught bad_numeric_cast #3\n"; caught_exception = true; }
if ( !caught_exception ) ++err_count;
caught_exception = false;
try { ul = numeric_cast<unsigned long>( small_negative_value ); }
catch (bad_numeric_cast)
{ cout<<"caught bad_numeric_cast #4\n"; caught_exception = true; }
if ( !caught_exception ) ++err_count;
caught_exception = false;
try { numeric_cast<int>( std::numeric_limits<double>::max() ); }
catch (bad_numeric_cast)
{ cout<<"caught bad_numeric_cast #5\n"; caught_exception = true; }
if ( !caught_exception ) ++err_count;
cout << err_count << " errors detected\nTest "
<< (err_count==0 ? "passed\n" : "failed\n");
return err_count;
} // main

View File

@@ -78,9 +78,6 @@ int main()
compressed_pair<non_empty1, non_empty2> cp1d(non_empty2(9));
assert(cp1d.second() == non_empty2(9));
assert(cp1d.first() == non_empty1());
compressed_pair<int, double> cp1e(cp1);
compressed_pair<empty_UDT, int> cp2(2);
assert(cp2.second() == 2);
compressed_pair<int, empty_UDT> cp3(1);
@@ -137,9 +134,7 @@ template class boost::compressed_pair<empty_UDT, empty_POD_UDT>;
// first references:
template double& compressed_pair<double, int&>::first();
template int& compressed_pair<double, int&>::second();
#if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95))
template compressed_pair<double, int&>::compressed_pair(int&);
#endif
template compressed_pair<double, int&>::compressed_pair(call_traits<double>::param_type,int&);
//
// and then arrays:
@@ -147,9 +142,7 @@ template compressed_pair<double, int&>::compressed_pair(call_traits<double>::par
template call_traits<int[2]>::reference compressed_pair<double, int[2]>::second();
#endif
template call_traits<double>::reference compressed_pair<double, int[2]>::first();
#if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95))
template compressed_pair<double, int[2]>::compressed_pair(call_traits<double>::param_type);
#endif
template compressed_pair<double, int[2]>::compressed_pair(const double&);
template compressed_pair<double, int[2]>::compressed_pair();
#endif // __MWERKS__
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION

View File

@@ -75,9 +75,7 @@ namespace details
template <typename T>
inline void cp_swap(T& t1, T& t2)
{
#ifndef __GNUC__
using std::swap;
#endif
swap(t1, t2);
}

View File

@@ -42,10 +42,6 @@ namespace boost
// have one template single-argument constructor
// in place of two specific constructors:
//
template <class T1, class T2>
class compressed_pair;
namespace detail{
template <class A, class T1, class T2>
@@ -108,8 +104,6 @@ public:
{
init_one<best_convertion_traits<A, T1, T2>::value>::init(val, &_first, &_second);
}
compressed_pair_0(const ::boost::compressed_pair<T1,T2>& x)
: _first(x._first), _second(x._second) {}
first_reference first() { return _first; }
first_const_reference first() const { return _first; }
@@ -148,8 +142,6 @@ public:
{
init_one<best_convertion_traits<A, T1, T2>::value>::init(val, &_first, static_cast<T2*>(this));
}
compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x)
: T2(x), _first(x._first) {}
first_reference first() { return _first; }
first_const_reference first() const { return _first; }
@@ -188,8 +180,6 @@ public:
{
init_one<best_convertion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), &_second);
}
compressed_pair_2(const ::boost::compressed_pair<T1,T2>& x)
: T1(x), _second(x._second) {}
first_reference first() { return *this; }
first_const_reference first() const { return *this; }
@@ -226,8 +216,6 @@ public:
{
init_one<best_convertion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), static_cast<T2*>(this));
}
compressed_pair_3(const ::boost::compressed_pair<T1,T2>& x)
: T1(x), T2(x) {}
first_reference first() { return *this; }
first_const_reference first() const { return *this; }
@@ -259,8 +247,6 @@ public:
compressed_pair_4(first_param_type x, second_param_type) : T1(x) {}
// only one single argument constructor since T1 == T2
explicit compressed_pair_4(first_param_type x) : T1(x) {}
compressed_pair_4(const ::boost::compressed_pair& x)
: T1(x){}
first_reference first() { return *this; }
first_const_reference first() const { return *this; }
@@ -294,9 +280,7 @@ public:
compressed_pair_5() : _first(), _second() {}
compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {}
// only one single argument constructor since T1 == T2
explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {}
compressed_pair_5(const ::boost::compressed_pair<T1,T2>& c)
: _first(c.first()), _second(c.second()) {}
explicit compressed_pair_5(first_param_type x) : _first(x), _second() {}
first_reference first() { return _first; }
first_const_reference first() const { return _first; }
@@ -469,4 +453,3 @@ inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
#endif // BOOST_OB_COMPRESSED_PAIR_HPP

View File

@@ -7,8 +7,7 @@
#include <functional>
#include <algorithm>
#include <iostream>
#include <boost/pending/iterator_adaptors.hpp>
#include <boost/pending/integer_range.hpp>
#include <boost/iterator_adaptors.hpp>
int
main(int, char*[])
@@ -16,7 +15,6 @@ main(int, char*[])
// This is a simple example of using the transform_iterators class to
// generate iterators that multiply the value returned by dereferencing
// the iterator. In this case we are multiplying by 2.
// Would be cooler to use lambda library in this example.
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };

View File

@@ -1,176 +0,0 @@
// Demonstrate and test boost/operators.hpp on std::iterators -------------//
// (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.
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 13 Jun 00 Added const version of the iterator tests (Jeremy Siek)
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
#include <boost/config.hpp>
#include <iostream>
#include <algorithm>
#include <functional>
#include <boost/pending/iterator_adaptors.hpp>
#include <boost/pending/iterator_tests.hpp>
#include <boost/pending/integer_range.hpp>
struct my_iterator_tag : public std::random_access_iterator_tag { };
using boost::dummyT;
struct my_iter_traits {
typedef dummyT value_type;
typedef dummyT* pointer;
typedef dummyT& reference;
typedef my_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
};
struct my_const_iter_traits {
typedef dummyT value_type;
typedef const dummyT* pointer;
typedef const dummyT& reference;
typedef my_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
};
typedef boost::iterator_adaptors
<dummyT*, const dummyT*,
my_iter_traits, my_const_iter_traits> My;
struct mult_functor {
typedef int result_type;
typedef int argument_type;
// Functors used with transform_iterator must be
// DefaultConstructible, as the transform_iterator must be
// DefaultConstructible to satisfy the requirements for
// TrivialIterator.
mult_functor() { }
mult_functor(int aa) : a(aa) { }
int operator()(int b) const { return a * b; }
int a;
};
template <class Pair>
struct select1st_
: public std::unary_function<Pair, typename Pair::first_type>
{
const typename Pair::first_type& operator()(const Pair& x) const {
return x.first;
}
typename Pair::first_type& operator()(Pair& x) const {
return x.first;
}
};
int
main()
{
dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),
dummyT(3), dummyT(4), dummyT(5) };
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);
// Test the iterator_adaptors
{
My::iterator i = array;
boost::random_access_iterator_test(i, N, array);
My::const_iterator j = array;
boost::random_access_iterator_test(j, N, array);
boost::const_nonconst_iterator_test(i, ++j);
}
// Test transform_iterator
{
int x[N], y[N];
for (int k = 0; k < N; ++k)
x[k] = k;
std::copy(x, x + N, y);
for (int k2 = 0; k2 < N; ++k2)
x[k2] = x[k2] * 2;
boost::transform_iterator<mult_functor, int*,
boost::iterator<std::random_access_iterator_tag,int> >::type
i(y, mult_functor(2));
boost::random_access_iterator_test(i, N, x);
}
// Test indirect_iterators
{
dummyT* ptr[N];
for (int k = 0; k < N; ++k)
ptr[k] = array + k;
typedef boost::indirect_iterators<dummyT**, dummyT*, const dummyT*,
boost::iterator<std::random_access_iterator_tag, dummyT*>,
boost::iterator<std::random_access_iterator_tag, dummyT>,
boost::iterator<std::random_access_iterator_tag, const dummyT>
> Indirect;
Indirect::iterator i = ptr;
boost::random_access_iterator_test(i, N, array);
Indirect::const_iterator j = ptr;
boost::random_access_iterator_test(j, N, array);
boost::const_nonconst_iterator_test(i, ++j);
}
// Test projection_iterators
{
typedef std::pair<dummyT,dummyT> Pair;
Pair pair_array[N];
for (int k = 0; k < N; ++k)
pair_array[k].first = array[k];
typedef boost::projection_iterators<select1st_<Pair>,
Pair*, const Pair*,
boost::iterator<std::random_access_iterator_tag, Pair>,
boost::iterator<std::random_access_iterator_tag, const Pair>
> Projection;
Projection::iterator i = pair_array;
boost::random_access_iterator_test(i, N, array);
Projection::const_iterator j = pair_array;
boost::random_access_iterator_test(j, N, array);
boost::const_nonconst_iterator_test(i, ++j);
}
// Test reverse_iterators
{
dummyT reversed[N];
std::copy(array, array + N, reversed);
std::reverse(reversed, reversed + N);
typedef boost::reverse_iterators<dummyT*, const dummyT*,
boost::iterator<std::random_access_iterator_tag,dummyT>,
boost::iterator<std::random_access_iterator_tag,const dummyT>
> Reverse;
Reverse::iterator i = reversed + N;
boost::random_access_iterator_test(i, N, array);
Reverse::const_iterator j = reversed + N;
boost::random_access_iterator_test(j, N, array);
boost::const_nonconst_iterator_test(i, ++j);
}
// Test integer_range's iterators
{
int int_array[] = { 0, 1, 2, 3, 4, 5 };
boost::integer_range<int> r(0, 5);
boost::random_access_iterator_test(r.begin(), r.size(), int_array);
}
std::cout << "test successful " << std::endl;
return 0;
}

View File

@@ -13,9 +13,7 @@
align="center" width="277" height="86">
<h1>Header
<a href="../../boost/pending/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a>
and
<a href="../../boost/pending/integer_range.hpp">boost/integer_range.hpp</a></h1>
<a href="../../boost/pending/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a></h1>
<p>The file <tt>boost/iterator_adaptors.hpp</tt>
includes the main <tt>iterator_adaptors</tt> class and several other classes
@@ -25,16 +23,8 @@ for constructing commonly used iterator adaptors.</p>
<li><a href="#iterator_adaptors"><tt>iterator_adaptors</tt></a>.
<li><a href="#iterator_adaptor"><tt>iterator_adaptor</tt></a>.
<li><a href="#transform_iterator"><tt>transform_iterator</tt></a>
<li><a href="#indirect_iterators"><tt>Indirect Iterator Adaptors</tt></a>
<li><a href="#projection_iterators"><tt>Projection Iterator Adaptors</tt></a>
<li><a href="#indirect_iterators"><tt>indirect_iterators</tt></a>
<li><a href="#reverse_iterators"><tt>reverse_iterators</tt></a>
</ul>
<p>The file <tt>boost/integer_range.hpp</tt> includes a class that
uses iterator adaptors to create an iterator that increments over a
range of integers. The file also includes a &quot;container&quot; type
that creates a container-interface for the range of integers.
<ul>
<li><a href="#integer_range"><tt>integer_range</tt></a>
</ul>
@@ -49,11 +39,7 @@ interactions. He also contributed the <tt>indirect_iterators</tt> and
<a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>
contributed <tt>transform_iterator</tt>, <tt>integer_range</tt>,
and this documentation.<br>
<a href="http://www.boost.org/people/john_potter.htm">John Potter</a>
contributed <tt>indirect_iterator</tt> and <tt>projection_iterator</tt>
and made some simplifications to <tt>iterator_adaptor</tt>.
and this documentation.
<h3><a name="iterator_adaptors">The Iterator Adaptors Class</a></h3>
@@ -74,10 +60,10 @@ follows:
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class Iterator,
class ConstIterator,
template &lt;class Iterator,
class ConstIterator,
class Traits = std::iterator_traits&lt;Iterator&gt;,
class ConstTraits = std::iterator_traits&lt;ConstIterator&gt;,
class ConstTraits = std::iterator_traits&lt;ConstIterator&gt;,
class Policies = default_iterator_policies&gt;
struct iterator_adaptors
{
@@ -133,7 +119,7 @@ struct default_iterator_policies
{ return *x; }
template &lt;class Iterator&gt;
static void increment(Iterator& x)
void increment(Iterator& x) const
{ ++x; }
template &lt;class Iterator1, class Iterator2&gt;
@@ -142,12 +128,12 @@ struct default_iterator_policies
// required for a BidirectionalIterator
template &lt;class Iterator&gt;
static void decrement(Iterator& x)
void decrement(Iterator& x) const
{ --x; }
// required for a RandomAccessIterator
template &lt;class Iterator, class DifferenceType&gt;
static void advance(Iterator& x, DifferenceType n)
void advance(Iterator& x, DifferenceType n) const
{ x += n; }
template &lt;class Difference, class Iterator1, class Iterator2&gt;
@@ -177,18 +163,20 @@ constructors.
This is the class used inside of the <tt>iterator_adaptors</tt> type
generator. Use this class directly (instead of using
<tt>iterator_adaptors</tt>) when you are interested in creating only
one of the iterator types (either const or non-const) or when there is
no difference between the const and non-const versions of the iterator
type (often this is because there is only a const (read-only) version
of the iterator, as is the case for <tt>std::set</tt>'s iterators).
<tt>iterator_adaptors</tt>) when there is no difference between the
const and non-const versions of the iterator type. Often this is
because there is only a const (read-only) version of the iterator, as
is the case for <tt>std::set</tt>'s iterators. Use the same type for
the <tt>Iterator</tt> and <tt>NonconstIterator</tt> template
arguments.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class Iterator,
template &lt;class Iterator,
class Policies = default_iterator_policies,
class NonconstIterator = Iterator,
class Traits = std::iterator_traits&lt;Iterator&gt; &gt;
struct iterator_adaptor;
</PRE></TD></TABLE>
@@ -231,7 +219,6 @@ href="#2">[2]</a>.
template &lt;class AdaptableUnaryFunction&gt;
struct transform_iterator_policies : public default_iterator_policies
{
transform_iterator_policies() { }
transform_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { }
template &lt;class Reference, class Iterator&gt;
@@ -332,234 +319,67 @@ main(int, char*[])
</PRE></TD></TABLE>
<h3><a name="indirect_iterators">The Indirect Iterator Adaptors</a></h3>
<h3><a name="indirect_iterators">The Indirect Iterators Class</a></h3>
It is not all that uncommon to create data structures that consist of
pointers to pointers. For such a structure it might be nice to have an
iterator that applies a double-dereference inside the
<tt>operator*()</tt>. The implementation of this is similar to the
<tt>transform_iterators</tt><a href="#3">[3]</a>. When talking about a
data structure of pointers to pointers (or more generally, iterators
to iterators), we call the first level iterators the <i>outer</i>
iterators and the second level iterators the <i>inner</i>
iterators. For example, if the outer iterator type is <tt>T**</tt>
then the inner iterator type is <tt>T*</tt>.
To implement the indirect adaptors, we first create a policies class
which does a double-dereference in the <tt>dereference()</tt> method.
<tt>transform_iterators</tt><a href="#3">[3]</a>. We first create a
policies class which does a double-dereference in the
<tt>dereference()</tt> method. We then create a traits class, this
time also including a template parameter for the traits of the second
level iterators as well as the first. Lastly we wrap this up in the
type generator <tt>indirect_iterators</tt>, using
<tt>iterator_adaptors</tt> to do most of the work.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
struct indirect_iterator_policies : public default_iterator_policies
{
struct indirect_iterator_policies : public default_iterator_policies
{
template &lt;class Reference, class Iterator&gt;
Reference dereference(type&lt;Reference&gt;, const Iterator& x) const
{ return **x; }
};
</PRE></TD></TABLE>
{ return **x; }
};
We then create a traits class, including a template parameter for both
the inner and outer iterators and traits classes. The
<tt>difference_type</tt> and <tt>iterator_category</tt> come from the
outer iterator, while the <tt>value_type</tt>, <tt>pointer</tt>, and
<tt>reference</tt> types come from the inner iterator.
template &lt;class IndirectIterator,
class IndirectTraits = std::iterator_traits&lt;IndirectIterator&gt;,
class Traits =
std::iterator_traits&lt;typename IndirectTraits::value_type&gt;
&gt;
struct indirect_traits
{
typedef typename IndirectTraits::difference_type difference_type;
typedef typename Traits::value_type value_type;
typedef typename Traits::pointer pointer;
typedef typename Traits::reference reference;
typedef typename IndirectTraits::iterator_category iterator_category;
};
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class OuterIterator, class InnerIterator,
class OuterTraits = std::iterator_traits&lt;OuterIterator&gt;,
class InnerTraits = std::iterator_traits&lt;InnerIterator&gt;
&gt;
struct indirect_traits
{
typedef typename OuterTraits::difference_type difference_type;
typedef typename InnerTraits::value_type value_type;
typedef typename InnerTraits::pointer pointer;
typedef typename InnerTraits::reference reference;
typedef typename OuterTraits::iterator_category iterator_category;
};
</PRE></TD></TABLE>
Lastly we wrap this up in two type generators:
<tt>indirect_iterator</tt> for creating a single indirect iterator
type, and <tt>indirect_iterators</tt> for creating an const/non-const
pair of indirect iterator types. We use the <tt>iterator_adaptor</tt>
and <tt>iterator_adaptors</tt> classes here to do most of the work.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class OuterIterator, class InnerIterator,
class OuterTraits = std::iterator_traits&lt;OuterIterator&gt;,
class InnerTraits = std::iterator_traits&lt;InnerIterator&gt;
&gt;
struct indirect_iterator
{
typedef iterator_adaptor&lt;OuterIterator,
indirect_iterator_policies,
indirect_traits&lt;OuterIterator, InnerIterator,
OuterTraits, InnerTraits&gt;
&gt; type;
};
template &lt;class OuterIterator, // Mutable or Immutable, does not matter
class InnerIterator, // Mutable
class ConstInnerIterator, // Immutable
class OuterTraits = std::iterator_traits&lt;OuterIterator&gt;,
class InnerTraits = std::iterator_traits&lt;InnerIterator&gt;,
class ConstInnerTraits = std::iterator_traits&lt;ConstInnerIterator&gt;
&gt;
struct indirect_iterators
{
typedef iterator_adaptors&lt;OuterIterator, OuterIterator,
indirect_traits&lt;OuterIterator, InnerIterator,
OuterTraits, InnerTraits&gt;,
indirect_traits&lt;OuterIterator, ConstInnerIterator,
OuterTraits, ConstInnerTraits&gt;,
indirect_iterator_policies
&gt; Adaptors;
template &lt;class IndirectIterator, class ConstIndirectIterator,
class IndirectTraits =
std::iterator_traits&lt;IndirectIterator&gt;,
class ConstIndirectTraits =
std::iterator_traits&lt;ConstIndirectIterator&gt;,
class Traits =
std::iterator_traits&lt;typename IndirectTraits::value_type&gt;
&gt;
struct indirect_iterators
{
typedef typename IndirectTraits::value_type Iterator;
typedef typename Traits::value_type ValueType;
typedef iterator_adaptors&lt;IndirectIterator, ConstIndirectIterator,
indirect_traits&lt;IndirectIterator, IndirectTraits, Traits&gt;,
indirect_traits&lt;ConstIndirectIterator, ConstIndirectTraits, Traits&gt;,
indirect_iterator_policies
&gt; Adaptors;
typedef typename Adaptors::iterator iterator;
typedef typename Adaptors::const_iterator const_iterator;
};
};
</PRE></TD></TABLE>
<h3><a name="projection_iterators">The Projection Iterator Adaptors</a></h3>
The projection iterator adaptor is very similar to the transform
iterator, except for a subtle difference in the return type: the
tranform iterator returns the result of the unary function by value,
whereas the projection iterator returns the result by reference.
Therefore, these two adaptors cater to different kinds of unary
functions. Transform iterator caters to functions that create new
objects, whereas projection iterator caters to a function that somehow
obtains a reference to an object that already exists. An example of a
unary function that is suitable for use with the projection adaptor is
<tt>select1st_</tt>:
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class Pair&gt;
struct select1st_
: public std::unary_function&lt;Pair, typename Pair::first_type&gt;
{
const typename Pair::first_type& operator()(const Pair& x) const {
return x.first;
}
typename Pair::first_type& operator()(Pair& x) const {
return x.first;
}
};
</PRE></TD></TABLE>
The implementation of projection iterator is as follows. First, the
policies class is the same as the transform iterator's policies class.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class AdaptableUnaryFunction&gt;
struct projection_iterator_policies : public default_iterator_policies
{
projection_iterator_policies() { }
projection_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { }
template &lt;class Reference, class Iterator&gt;
Reference dereference (type&lt;Reference&gt;, Iterator const& iter) const {
return m_f(*iter);
}
AdaptableUnaryFunction m_f;
};
</PRE></TD></TABLE>
Next we have two traits classes. We use <tt>value_type&</tt> for the
reference type of the mutable projection iterator, and <tt>const
value_type&</tt> for the immutable projection iterator.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class AdaptableUnaryFunction, class Traits&gt;
struct projection_iterator_traits {
typedef typename AdaptableUnaryFunction::result_type value_type;
typedef value_type& reference;
typedef value_type* pointer;
typedef typename Traits::difference_type difference_type;
typedef typename Traits::iterator_category iterator_category;
};
template &lt;class AdaptableUnaryFunction, class Traits&gt;
struct const_projection_iterator_traits {
typedef typename AdaptableUnaryFunction::result_type value_type;
typedef value_type const& reference;
typedef value_type const* pointer;
typedef typename Traits::difference_type difference_type;
typedef typename Traits::iterator_category iterator_category;
};
</PRE></TD></TABLE>
And to finish up, we create three generator classes that
use <tt>iterator_adaptor</tt> to create the projection iterator
types. The class <tt>projection_iterator</tt> creates a mutable
projection iterator type. The class <tt>const_projection_iterator</tt>
creates an immutable projection iterator type, and
<tt>projection_iterators</tt> creates both mutable and immutable
projection iterator types.
<p>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class AdaptableUnaryFunction, class Iterator,
class Traits = std::iterator_traits&lt;Iterator&gt;
&gt;
struct projection_iterator {
typedef projection_iterator_traits&lt;AdaptableUnaryFunction, Traits&gt;
Projection_Traits;
typedef iterator_adaptor&lt;Iterator,
projection_iterator_policies&lt;AdaptableUnaryFunction&gt;,
Projection_Traits&gt; type;
};
template &lt;class AdaptableUnaryFunction, class Iterator,
class Traits = std::iterator_traits&lt;Iterator&gt;
&gt;
struct const_projection_iterator {
typedef const_projection_iterator_traits&lt;AdaptableUnaryFunction,
Traits&gt; Projection_Traits;
typedef iterator_adaptor&lt;Iterator,
projection_iterator_policies&lt;AdaptableUnaryFunction&gt;,
Projection_Traits&gt; type;
};
template &lt;class AdaptableUnaryFunction, class Iterator, class ConstIterator,
class Traits = std::iterator_traits&lt;Iterator&gt;,
class ConstTraits = std::iterator_traits&lt;ConstIterator&gt;
&gt;
struct projection_iterators {
typedef projection_iterator_traits&lt;AdaptableUnaryFunction, Traits&gt;
Projection_Traits;
typedef const_projection_iterator_traits&lt;AdaptableUnaryFunction,
ConstTraits&gt; Const_Projection_Traits;
typedef iterator_adaptors&lt;Iterator, ConstIterator,
Projection_Traits, Const_Projection_Traits,
projection_iterator_policies&lt;AdaptableUnaryFunction&gt; &gt; Adaptors;
typedef typename Adaptors::iterator iterator;
typedef typename Adaptors::const_iterator const_iterator;
};
</PRE></TD></TABLE>
<h3><a name="reverse_iterators">The Reverse Iterators Class</a></h3>
<p>
@@ -674,9 +494,9 @@ iterator.
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2>
<TR><TD WIDTH=30 VALIGN=TOP></TD><TD>
<PRE>
template &lt;class IntegerType&gt;
struct counting_iterator_policies : public default_iterator_policies
{
template &lt;class IntegerType&gt;
IntegerType dereference(type&lt;IntegerType&gt;, const IntegerType& i) const
{ return i; }
};
@@ -797,7 +617,7 @@ uses the three adaptors.
<hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->27 Nov 2000<!--webbot bot="Timestamp" endspan i-checksum="15248" --></p>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->27 Sep 2000<!--webbot bot="Timestamp" endspan i-checksum="14936" --></p>
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
modify, sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided &quot;as is&quot;

View File

@@ -35,7 +35,7 @@ a function which returns a std::pair&lt;&gt;. The effect of the <TT>tie()</TT>
function is to allow the assignment of the two values of the pair to
two separate variables. The idea for this comes from Jaakko
J&#228;rvi's Binders&nbsp;[<A
HREF="../graph/doc/bibliography.html#jaakko_tuple_assign">1</A>].
HREF="../graph/docs/bibliography.html#jaakko_tuple_assign">1</A>].
<P>

View File

@@ -608,7 +608,7 @@ int main()
value_test(false, (boost::is_convertible<const int *, int*>::value));
value_test(false, (boost::is_convertible<const int&, int&>::value));
value_test(true, (boost::is_convertible<int*, int[2]>::value));
value_test(false, (boost::is_convertible<int*, int[2]>::value));
value_test(false, (boost::is_convertible<const int*, int[3]>::value));
value_test(true, (boost::is_convertible<const int&, int>::value));
value_test(true, (boost::is_convertible<int(&)[4], const int*>::value));
@@ -641,4 +641,3 @@ int main()

View File

@@ -35,7 +35,6 @@ struct ct_checker
#ifdef BOOST_MSVC
#define value_test(v, x) ++test_count;\
{typedef ct_checker<(x)> this_is_a_compile_time_check_;}\
if(!do_compare((int)v,(int)x)){++failures; std::cout << "checking value of " << #x << "...failed" << std::endl;}
#else
#define value_test(v, x) ++test_count;\
@@ -109,4 +108,3 @@ unsigned test_count = 0;
#endif // BOOST_TYPE_TRAITS_TEST_HPP