forked from boostorg/utility
Compare commits
4 Commits
svn-branch
...
svn-branch
Author | SHA1 | Date | |
---|---|---|---|
|
df2ef006c7 | ||
|
22d30b566b | ||
|
4476a85d55 | ||
|
f02dc90bfc |
263
counting_iterator_test.cpp
Normal file
263
counting_iterator_test.cpp
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
// (C) Copyright David Abrahams 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.
|
||||||
|
//
|
||||||
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
//
|
||||||
|
// Revision History
|
||||||
|
// 16 Feb 2001 Added a missing const. Made the tests run (somewhat) with
|
||||||
|
// plain MSVC again. (David Abrahams)
|
||||||
|
// 11 Feb 2001 #if 0'd out use of counting_iterator on non-numeric types in
|
||||||
|
// MSVC without STLport, so that the other tests may proceed
|
||||||
|
// (David Abrahams)
|
||||||
|
// 04 Feb 2001 Added use of iterator_tests.hpp (David Abrahams)
|
||||||
|
// 28 Jan 2001 Removed not_an_iterator detritus (David Abrahams)
|
||||||
|
// 24 Jan 2001 Initial revision (David Abrahams)
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
# pragma warning(disable:4786) // identifier truncated in debug info
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/pending/iterator_tests.hpp>
|
||||||
|
#include <boost/counting_iterator.hpp>
|
||||||
|
#include <boost/detail/iterator.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <climits>
|
||||||
|
#include <iterator>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <boost/utility.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
#include <cassert>
|
||||||
|
#ifndef BOOST_NO_LIMITS
|
||||||
|
# include <limits>
|
||||||
|
#endif
|
||||||
|
#ifndef BOOST_NO_SLIST
|
||||||
|
# include <slist>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <class T> struct is_numeric
|
||||||
|
{
|
||||||
|
enum { value =
|
||||||
|
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
||||||
|
std::numeric_limits<T>::is_specialized
|
||||||
|
#else
|
||||||
|
// Causes warnings with GCC, but how else can I detect numeric types at
|
||||||
|
// compile-time?
|
||||||
|
(boost::is_convertible<int,T>::value &&
|
||||||
|
boost::is_convertible<T,int>::value)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Special tests for RandomAccess CountingIterators.
|
||||||
|
template <class CountingIterator>
|
||||||
|
void category_test(
|
||||||
|
CountingIterator start,
|
||||||
|
CountingIterator finish,
|
||||||
|
std::random_access_iterator_tag)
|
||||||
|
{
|
||||||
|
typedef typename
|
||||||
|
boost::detail::iterator_traits<CountingIterator>::difference_type
|
||||||
|
difference_type;
|
||||||
|
difference_type distance = boost::detail::distance(start, finish);
|
||||||
|
|
||||||
|
// Pick a random position internal to the range
|
||||||
|
difference_type offset = (unsigned)rand() % distance;
|
||||||
|
assert(offset >= 0);
|
||||||
|
CountingIterator internal = start;
|
||||||
|
std::advance(internal, offset);
|
||||||
|
|
||||||
|
// Try some binary searches on the range to show that it's ordered
|
||||||
|
assert(std::binary_search(start, finish, *internal));
|
||||||
|
CountingIterator x,y;
|
||||||
|
boost::tie(x,y) = std::equal_range(start, finish, *internal);
|
||||||
|
assert(boost::detail::distance(x, y) == 1);
|
||||||
|
|
||||||
|
// Show that values outside the range can't be found
|
||||||
|
assert(!std::binary_search(start, boost::prior(finish), *finish));
|
||||||
|
|
||||||
|
// Do the generic random_access_iterator_test
|
||||||
|
typedef typename CountingIterator::value_type value_type;
|
||||||
|
std::vector<value_type> v;
|
||||||
|
for (value_type z = *start; z != *finish; ++z)
|
||||||
|
v.push_back(z);
|
||||||
|
if (v.size() >= 2)
|
||||||
|
{
|
||||||
|
// Note that this test requires a that the first argument is
|
||||||
|
// dereferenceable /and/ a valid iterator prior to the first argument
|
||||||
|
boost::random_access_iterator_test(start + 1, v.size() - 1, v.begin() + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special tests for bidirectional CountingIterators
|
||||||
|
template <class CountingIterator>
|
||||||
|
void category_test(CountingIterator start, CountingIterator finish, std::bidirectional_iterator_tag)
|
||||||
|
{
|
||||||
|
if (finish != start
|
||||||
|
&& finish != boost::next(start)
|
||||||
|
&& finish != boost::next(boost::next(start)))
|
||||||
|
{
|
||||||
|
// Note that this test requires a that the first argument is
|
||||||
|
// dereferenceable /and/ a valid iterator prior to the first argument
|
||||||
|
boost::bidirectional_iterator_test(boost::next(start), boost::next(*start), boost::next(boost::next(*start)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CountingIterator>
|
||||||
|
void category_test(CountingIterator start, CountingIterator finish, std::forward_iterator_tag)
|
||||||
|
{
|
||||||
|
if (finish != start && finish != boost::next(start))
|
||||||
|
boost::forward_iterator_test(start, *start, boost::next(*start));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CountingIterator>
|
||||||
|
void test_aux(CountingIterator start, CountingIterator finish)
|
||||||
|
{
|
||||||
|
typedef typename CountingIterator::iterator_category category;
|
||||||
|
typedef typename CountingIterator::value_type value_type;
|
||||||
|
|
||||||
|
// If it's a RandomAccessIterator we can do a few delicate tests
|
||||||
|
category_test(start, finish, category());
|
||||||
|
|
||||||
|
// Okay, brute force...
|
||||||
|
for (CountingIterator p = start; p != finish && boost::next(p) != finish; ++p)
|
||||||
|
{
|
||||||
|
assert(boost::next(*p) == *boost::next(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
// prove that a reference can be formed to these values
|
||||||
|
typedef typename CountingIterator::value_type value;
|
||||||
|
const value* q = &*start;
|
||||||
|
(void)q; // suppress unused variable warning
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Incrementable>
|
||||||
|
void test(Incrementable start, Incrementable finish)
|
||||||
|
{
|
||||||
|
test_aux(boost::make_counting_iterator(start), boost::make_counting_iterator(finish));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Integer>
|
||||||
|
void test_integer(Integer* = 0) // default arg works around MSVC bug
|
||||||
|
{
|
||||||
|
Integer start = 0;
|
||||||
|
Integer finish = 120;
|
||||||
|
test(start, finish);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Container>
|
||||||
|
void test_container(Container* = 0) // default arg works around MSVC bug
|
||||||
|
{
|
||||||
|
Container c(1 + (unsigned)rand() % 1673);
|
||||||
|
|
||||||
|
const typename Container::iterator start = c.begin();
|
||||||
|
|
||||||
|
// back off by 1 to leave room for dereferenceable value at the end
|
||||||
|
typename Container::iterator finish = start;
|
||||||
|
std::advance(finish, c.size() - 1);
|
||||||
|
|
||||||
|
test(start, finish);
|
||||||
|
|
||||||
|
typedef typename Container::const_iterator const_iterator;
|
||||||
|
test(const_iterator(start), const_iterator(finish));
|
||||||
|
}
|
||||||
|
|
||||||
|
class my_int1 {
|
||||||
|
public:
|
||||||
|
my_int1() { }
|
||||||
|
my_int1(int x) : m_int(x) { }
|
||||||
|
my_int1& operator++() { ++m_int; return *this; }
|
||||||
|
bool operator==(const my_int1& x) const { return m_int == x.m_int; }
|
||||||
|
private:
|
||||||
|
int m_int;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
template <>
|
||||||
|
struct counting_iterator_traits<my_int1> {
|
||||||
|
typedef std::ptrdiff_t difference_type;
|
||||||
|
typedef std::forward_iterator_tag iterator_category;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class my_int2 {
|
||||||
|
public:
|
||||||
|
typedef void value_type;
|
||||||
|
typedef void pointer;
|
||||||
|
typedef void reference;
|
||||||
|
typedef std::ptrdiff_t difference_type;
|
||||||
|
typedef std::bidirectional_iterator_tag iterator_category;
|
||||||
|
|
||||||
|
my_int2() { }
|
||||||
|
my_int2(int x) : m_int(x) { }
|
||||||
|
my_int2& operator++() { ++m_int; return *this; }
|
||||||
|
my_int2& operator--() { --m_int; return *this; }
|
||||||
|
bool operator==(const my_int2& x) const { return m_int == x.m_int; }
|
||||||
|
private:
|
||||||
|
int m_int;
|
||||||
|
};
|
||||||
|
|
||||||
|
class my_int3 {
|
||||||
|
public:
|
||||||
|
typedef void value_type;
|
||||||
|
typedef void pointer;
|
||||||
|
typedef void reference;
|
||||||
|
typedef std::ptrdiff_t difference_type;
|
||||||
|
typedef std::random_access_iterator_tag iterator_category;
|
||||||
|
|
||||||
|
my_int3() { }
|
||||||
|
my_int3(int x) : m_int(x) { }
|
||||||
|
my_int3& operator++() { ++m_int; return *this; }
|
||||||
|
my_int3& operator+=(std::ptrdiff_t n) { m_int += n; return *this; }
|
||||||
|
std::ptrdiff_t operator-(const my_int3& x) const { return m_int - x.m_int; }
|
||||||
|
my_int3& operator--() { --m_int; return *this; }
|
||||||
|
bool operator==(const my_int3& x) const { return m_int == x.m_int; }
|
||||||
|
bool operator!=(const my_int3& x) const { return m_int != x.m_int; }
|
||||||
|
bool operator<(const my_int3& x) const { return m_int < x.m_int; }
|
||||||
|
private:
|
||||||
|
int m_int;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// Test the built-in integer types.
|
||||||
|
test_integer<char>();
|
||||||
|
test_integer<unsigned char>();
|
||||||
|
test_integer<signed char>();
|
||||||
|
test_integer<wchar_t>();
|
||||||
|
test_integer<short>();
|
||||||
|
test_integer<unsigned short>();
|
||||||
|
test_integer<int>();
|
||||||
|
test_integer<unsigned int>();
|
||||||
|
test_integer<long>();
|
||||||
|
test_integer<unsigned long>();
|
||||||
|
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
|
||||||
|
test_integer<long long>();
|
||||||
|
test_integer<unsigned long long>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// wrapping an iterator or non-built-in integer type causes an INTERNAL
|
||||||
|
// COMPILER ERROR in MSVC without STLport. I'm clueless as to why.
|
||||||
|
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT)
|
||||||
|
// Test user-defined type.
|
||||||
|
test_integer<my_int1>();
|
||||||
|
test_integer<my_int2>();
|
||||||
|
test_integer<my_int3>();
|
||||||
|
|
||||||
|
// Some tests on container iterators, to prove we handle a few different categories
|
||||||
|
test_container<std::vector<int> >();
|
||||||
|
test_container<std::list<int> >();
|
||||||
|
# ifndef BOOST_NO_SLIST
|
||||||
|
test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >();
|
||||||
|
# endif
|
||||||
|
|
||||||
|
// Also prove that we can handle raw pointers.
|
||||||
|
int array[2000];
|
||||||
|
test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1));
|
||||||
|
#endif
|
||||||
|
std::cout << "test successful " << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
41
fun_out_iter_example.cpp
Normal file
41
fun_out_iter_example.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
// (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.
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <boost/function_output_iterator.hpp>
|
||||||
|
|
||||||
|
struct string_appender {
|
||||||
|
string_appender(std::string& s) : m_str(s) { }
|
||||||
|
void operator()(const std::string& x) const {
|
||||||
|
m_str += x;
|
||||||
|
}
|
||||||
|
std::string& m_str;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int, char*[])
|
||||||
|
{
|
||||||
|
std::vector<std::string> x;
|
||||||
|
x.push_back("hello");
|
||||||
|
x.push_back(" ");
|
||||||
|
x.push_back("world");
|
||||||
|
x.push_back("!");
|
||||||
|
|
||||||
|
std::string s = "";
|
||||||
|
std::copy(x.begin(), x.end(),
|
||||||
|
boost::make_function_output_iterator(string_appender(s)));
|
||||||
|
|
||||||
|
std::cout << s << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
169
function_output_iterator.htm
Normal file
169
function_output_iterator.htm
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta name="generator" content="HTML Tidy, see www.w3.org">
|
||||||
|
<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>Function Output Iterator Adaptor Documentation</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#FFFFFF" text="#000000">
|
||||||
|
|
||||||
|
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
|
||||||
|
"center" width="277" height="86">
|
||||||
|
|
||||||
|
<h1>Function Output Iterator Adaptor</h1>
|
||||||
|
Defined in header <a href=
|
||||||
|
"../../boost/function_output_iterator.hpp">boost/function_output_iterator.hpp</a>
|
||||||
|
|
||||||
|
<p>The function output iterator adaptor makes it easier to create
|
||||||
|
custom output iterators. The adaptor takes a <a
|
||||||
|
href="http://www.sgi.com/tech/stl/UnaryFunction.html">Unary
|
||||||
|
Function</a> and creates a model of <a
|
||||||
|
href="http://www.sgi.com/tech/stl/OutputIterator.html">Output
|
||||||
|
Iterator</a>. Each item assigned to the output iterator is passed
|
||||||
|
as an argument to the unary function. The motivation for this
|
||||||
|
iterator is that creating a C++ Standard conforming output
|
||||||
|
iterator is non-trivial, particularly because the proper
|
||||||
|
implementation usually requires a proxy object. On the other hand,
|
||||||
|
creating a function (or function object) is much simpler.
|
||||||
|
|
||||||
|
<h2>Synopsis</h2>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<pre>
|
||||||
|
namespace boost {
|
||||||
|
template <class UnaryFunction>
|
||||||
|
class function_output_iterator;
|
||||||
|
|
||||||
|
template <class UnaryFunction>
|
||||||
|
function_output_iterator<UnaryFunction>
|
||||||
|
make_function_output_iterator(const UnaryFunction& f = UnaryFunction())
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<h3>Example</h3>
|
||||||
|
|
||||||
|
In this example we create an output iterator that appends
|
||||||
|
each item onto the end of a string, using the <tt>string_appender</tt>
|
||||||
|
function.
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<pre>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <boost/function_output_iterator.hpp>
|
||||||
|
|
||||||
|
struct string_appender {
|
||||||
|
string_appender(std::string& s) : m_str(s) { }
|
||||||
|
void operator()(const std::string& x) const {
|
||||||
|
m_str += x;
|
||||||
|
}
|
||||||
|
std::string& m_str;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int, char*[])
|
||||||
|
{
|
||||||
|
std::vector<std::string> x;
|
||||||
|
x.push_back("hello");
|
||||||
|
x.push_back(" ");
|
||||||
|
x.push_back("world");
|
||||||
|
x.push_back("!");
|
||||||
|
|
||||||
|
std::string s = "";
|
||||||
|
std::copy(x.begin(), x.end(),
|
||||||
|
boost::make_function_output_iterator(string_appender(s)));
|
||||||
|
|
||||||
|
std::cout << s << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h2><a name="function_output_iterator">The Function Output Iterator Class</a></h2>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<pre>
|
||||||
|
template <class UnaryFunction>
|
||||||
|
class function_output_iterator;
|
||||||
|
</pre>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
The <tt>function_output_iterator</tt> class creates an <a
|
||||||
|
href="http://www.sgi.com/tech/stl/OutputIterator.html">Output
|
||||||
|
Iterator</a> out of a
|
||||||
|
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">Unary
|
||||||
|
Function</a>. Each item assigned to the output iterator is passed
|
||||||
|
as an argument to the unary function.
|
||||||
|
|
||||||
|
<h3>Template Parameters</h3>
|
||||||
|
|
||||||
|
<table border>
|
||||||
|
<tr>
|
||||||
|
<th>Parameter
|
||||||
|
|
||||||
|
<th>Description
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td><tt>UnaryFunction</tt>
|
||||||
|
|
||||||
|
<td>The function type being wrapped. The return type of the
|
||||||
|
function is not used, so it can be <tt>void</tt>. The
|
||||||
|
function must be a model of <a
|
||||||
|
href="http://www.sgi.com/tech/stl/UnaryFunction.html">Unary
|
||||||
|
Function</a>.</td>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3>Concept Model</h3>
|
||||||
|
The function output iterator class is a model of <a
|
||||||
|
href="http://www.sgi.com/tech/stl/OutputIterator.html">Output
|
||||||
|
Iterator</a>.
|
||||||
|
|
||||||
|
<h2>Members</h3>
|
||||||
|
The function output iterator implements the member functions
|
||||||
|
and operators required of the <a
|
||||||
|
href="http://www.sgi.com/tech/stl/OutputIterator.html">Output
|
||||||
|
Iterator</a> concept. In addition it has the following constructor:
|
||||||
|
<pre>
|
||||||
|
explicit function_output_iterator(const UnaryFunction& f = UnaryFunction())
|
||||||
|
</pre>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h2><a name="make_function_output_iterator">The Function Output Iterator Object
|
||||||
|
Generator</a></h2>
|
||||||
|
|
||||||
|
The <tt>make_function_output_iterator()</tt> function provides a
|
||||||
|
more convenient way to create function output iterator objects. The
|
||||||
|
function saves the user the trouble of explicitly writing out the
|
||||||
|
iterator types. If the default argument is used, the function
|
||||||
|
type must be provided as an explicit template argument.
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<pre>
|
||||||
|
template <class UnaryFunction>
|
||||||
|
function_output_iterator<UnaryFunction>
|
||||||
|
make_function_output_iterator(const UnaryFunction& f = UnaryFunction())
|
||||||
|
</pre>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p>© Copyright Jeremy Siek 2001. Permission to copy, use,
|
||||||
|
modify, sell and distribute this document is granted provided this
|
||||||
|
copyright notice appears in all copies. This document is provided
|
||||||
|
"as is" without express or implied warranty, and with no claim as
|
||||||
|
to its suitability for any purpose.
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
27
iter_adaptor_fail_expected1.cpp
Normal file
27
iter_adaptor_fail_expected1.cpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// Test boost/pending/iterator_adaptors.hpp
|
||||||
|
|
||||||
|
// (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
|
||||||
|
// 21 Jan 01 Initial version (Jeremy Siek)
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <list>
|
||||||
|
#include <boost/pending/iterator_adaptors.hpp>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
typedef boost::iterator_adaptor<std::list<int>::iterator,
|
||||||
|
boost::default_iterator_policies,
|
||||||
|
int,int&,int*,std::bidirectional_iterator_tag> adaptor_type;
|
||||||
|
|
||||||
|
adaptor_type i;
|
||||||
|
i += 4;
|
||||||
|
return 0;
|
||||||
|
}
|
28
iter_adaptor_fail_expected2.cpp
Normal file
28
iter_adaptor_fail_expected2.cpp
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// Test boost/pending/iterator_adaptors.hpp
|
||||||
|
|
||||||
|
// (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
|
||||||
|
// 21 Jan 01 Initial version (Jeremy Siek)
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <boost/pending/iterator_adaptors.hpp>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
typedef boost::iterator_adaptor<std::istream_iterator<int>,
|
||||||
|
boost::default_iterator_policies,
|
||||||
|
int,int&,int*,std::input_iterator_tag> adaptor_type;
|
||||||
|
|
||||||
|
adaptor_type iter;
|
||||||
|
--iter;
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -1,458 +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
|
|
||||||
// 19 Feb 01 Take adavantage of improved iterator_traits to do more tests
|
|
||||||
// on MSVC. Hack around an MSVC-with-STLport internal compiler
|
|
||||||
// error. (David Abrahams)
|
|
||||||
// 11 Feb 01 Added test of operator-> for forward and input iterators.
|
|
||||||
// (Jeremy Siek)
|
|
||||||
// 11 Feb 01 Borland fixes (David Abrahams)
|
|
||||||
// 10 Feb 01 Use new adaptors interface. (David Abrahams)
|
|
||||||
// 10 Feb 01 Use new filter_ interface. (David Abrahams)
|
|
||||||
// 09 Feb 01 Use new reverse_ and indirect_ interfaces. Replace
|
|
||||||
// BOOST_NO_STD_ITERATOR_TRAITS with
|
|
||||||
// BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION to prove we've
|
|
||||||
// normalized to core compiler capabilities (David Abrahams)
|
|
||||||
// 08 Feb 01 Use Jeremy's new make_reverse_iterator form; add more
|
|
||||||
// comprehensive testing. Force-decay array function arguments to
|
|
||||||
// pointers.
|
|
||||||
// 07 Feb 01 Added tests for the make_xxx_iterator() helper functions.
|
|
||||||
// (Jeremy Siek)
|
|
||||||
// 07 Feb 01 Replaced use of xxx_pair_generator with xxx_generator where
|
|
||||||
// possible (which was all but the projection iterator).
|
|
||||||
// (Jeremy Siek)
|
|
||||||
// 06 Feb 01 Removed now-defaulted template arguments where possible
|
|
||||||
// Updated names to correspond to new generator naming convention.
|
|
||||||
// Added a trivial test for make_transform_iterator().
|
|
||||||
// Gave traits for const iterators a mutable value_type, per std.
|
|
||||||
// Resurrected my original tests for indirect iterators.
|
|
||||||
// (David Abrahams)
|
|
||||||
// 04 Feb 01 Fix for compilers without standard iterator_traits
|
|
||||||
// (David Abrahams)
|
|
||||||
// 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/iterator_adaptors.hpp>
|
|
||||||
#include <boost/pending/iterator_tests.hpp>
|
|
||||||
#include <boost/pending/integer_range.hpp>
|
|
||||||
#include <boost/concept_archetype.hpp>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <deque>
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
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_adaptor<dummyT*,
|
|
||||||
boost::default_iterator_policies, dummyT> my_iterator;
|
|
||||||
|
|
||||||
typedef boost::iterator_adaptor<const dummyT*,
|
|
||||||
boost::default_iterator_policies, const dummyT> const_my_iterator;
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct one_or_four {
|
|
||||||
bool operator()(dummyT x) const {
|
|
||||||
return x.foo() == 1 || x.foo() == 4;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::deque<int> storage;
|
|
||||||
typedef std::deque<int*> pointer_deque;
|
|
||||||
typedef std::set<storage::iterator> iterator_set;
|
|
||||||
|
|
||||||
void more_indirect_iterator_tests()
|
|
||||||
{
|
|
||||||
// For some reason all heck breaks loose in the compiler under these conditions.
|
|
||||||
#if !defined(BOOST_MSVC) || !defined(__STL_DEBUG)
|
|
||||||
storage store(1000);
|
|
||||||
std::generate(store.begin(), store.end(), rand);
|
|
||||||
|
|
||||||
pointer_deque ptr_deque;
|
|
||||||
iterator_set iter_set;
|
|
||||||
|
|
||||||
for (storage::iterator p = store.begin(); p != store.end(); ++p)
|
|
||||||
{
|
|
||||||
ptr_deque.push_back(&*p);
|
|
||||||
iter_set.insert(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef boost::indirect_iterator_pair_generator<
|
|
||||||
pointer_deque::iterator
|
|
||||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
, int
|
|
||||||
#endif
|
|
||||||
> IndirectDeque;
|
|
||||||
|
|
||||||
IndirectDeque::iterator db(ptr_deque.begin());
|
|
||||||
IndirectDeque::iterator de(ptr_deque.end());
|
|
||||||
assert(static_cast<std::size_t>(de - db) == store.size());
|
|
||||||
assert(db + store.size() == de);
|
|
||||||
IndirectDeque::const_iterator dci(db);
|
|
||||||
assert(db == dci);
|
|
||||||
assert(dci == db);
|
|
||||||
assert(dci != de);
|
|
||||||
assert(dci < de);
|
|
||||||
assert(dci <= de);
|
|
||||||
assert(de >= dci);
|
|
||||||
assert(de > dci);
|
|
||||||
dci = de;
|
|
||||||
assert(dci == de);
|
|
||||||
|
|
||||||
boost::random_access_iterator_test(db + 1, store.size() - 1, boost::next(store.begin()));
|
|
||||||
|
|
||||||
*db = 999;
|
|
||||||
assert(store.front() == 999);
|
|
||||||
|
|
||||||
typedef boost::indirect_iterator_generator<
|
|
||||||
iterator_set::iterator
|
|
||||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
, int
|
|
||||||
#endif
|
|
||||||
>::type indirect_set_iterator;
|
|
||||||
|
|
||||||
typedef boost::indirect_iterator_generator<
|
|
||||||
iterator_set::iterator,
|
|
||||||
const int
|
|
||||||
>::type const_indirect_set_iterator;
|
|
||||||
|
|
||||||
indirect_set_iterator sb(iter_set.begin());
|
|
||||||
indirect_set_iterator se(iter_set.end());
|
|
||||||
const_indirect_set_iterator sci(iter_set.begin());
|
|
||||||
assert(sci == sb);
|
|
||||||
assert(sci != se);
|
|
||||||
sci = se;
|
|
||||||
assert(sci == se);
|
|
||||||
|
|
||||||
*boost::prior(se) = 888;
|
|
||||||
assert(store.back() == 888);
|
|
||||||
assert(std::equal(sb, se, store.begin()));
|
|
||||||
|
|
||||||
boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]);
|
|
||||||
assert(std::equal(db, de, store.begin()));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Check that the policy concept checks and the default policy
|
|
||||||
// implementation match up.
|
|
||||||
boost::function_requires<
|
|
||||||
boost::RandomAccessIteratorPoliciesConcept<
|
|
||||||
boost::default_iterator_policies, int*,
|
|
||||||
boost::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t,
|
|
||||||
int*, int&>
|
|
||||||
> >();
|
|
||||||
|
|
||||||
// Test the iterator_adaptor
|
|
||||||
{
|
|
||||||
my_iterator i(array);
|
|
||||||
boost::random_access_iterator_test(i, N, array);
|
|
||||||
|
|
||||||
const_my_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_generator<mult_functor, int*>::type
|
|
||||||
i(y, mult_functor(2));
|
|
||||||
boost::input_iterator_test(i, x[0], x[1]);
|
|
||||||
boost::input_iterator_test(boost::make_transform_iterator(&y[0], mult_functor(2)), x[0], x[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test indirect_iterator_generator
|
|
||||||
{
|
|
||||||
dummyT* ptr[N];
|
|
||||||
for (int k = 0; k < N; ++k)
|
|
||||||
ptr[k] = array + k;
|
|
||||||
|
|
||||||
typedef boost::indirect_iterator_generator<dummyT**
|
|
||||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
, dummyT
|
|
||||||
#endif
|
|
||||||
>::type indirect_iterator;
|
|
||||||
|
|
||||||
typedef boost::indirect_iterator_generator<dummyT**, const dummyT>::type const_indirect_iterator;
|
|
||||||
|
|
||||||
indirect_iterator i(ptr);
|
|
||||||
boost::random_access_iterator_test(i, N, array);
|
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// check operator->
|
|
||||||
assert((*i).m_x == i->foo());
|
|
||||||
|
|
||||||
const_indirect_iterator j(ptr);
|
|
||||||
boost::random_access_iterator_test(j, N, array);
|
|
||||||
|
|
||||||
dummyT*const* const_ptr = ptr;
|
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array);
|
|
||||||
#endif
|
|
||||||
boost::const_nonconst_iterator_test(i, ++j);
|
|
||||||
|
|
||||||
more_indirect_iterator_tests();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test projection_iterator_pair_generator
|
|
||||||
{
|
|
||||||
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_iterator_pair_generator<select1st_<Pair>,
|
|
||||||
Pair*, const Pair*
|
|
||||||
> Projection;
|
|
||||||
|
|
||||||
Projection::iterator i(pair_array);
|
|
||||||
boost::random_access_iterator_test(i, N, array);
|
|
||||||
|
|
||||||
boost::random_access_iterator_test(boost::make_projection_iterator(pair_array, select1st_<Pair>()), N, array);
|
|
||||||
boost::random_access_iterator_test(boost::make_projection_iterator< select1st_<Pair> >(pair_array), N, array);
|
|
||||||
|
|
||||||
Projection::const_iterator j(pair_array);
|
|
||||||
boost::random_access_iterator_test(j, N, array);
|
|
||||||
|
|
||||||
boost::random_access_iterator_test(boost::make_const_projection_iterator(pair_array, select1st_<Pair>()), N, array);
|
|
||||||
boost::random_access_iterator_test(boost::make_const_projection_iterator<select1st_<Pair> >(pair_array), N, array);
|
|
||||||
|
|
||||||
boost::const_nonconst_iterator_test(i, ++j);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test reverse_iterator_generator
|
|
||||||
{
|
|
||||||
dummyT reversed[N];
|
|
||||||
std::copy(array, array + N, reversed);
|
|
||||||
std::reverse(reversed, reversed + N);
|
|
||||||
|
|
||||||
typedef boost::reverse_iterator_generator<dummyT*
|
|
||||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
, dummyT
|
|
||||||
#endif
|
|
||||||
>::type reverse_iterator;
|
|
||||||
|
|
||||||
reverse_iterator i(reversed + N);
|
|
||||||
boost::random_access_iterator_test(i, N, array);
|
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef boost::reverse_iterator_generator<const dummyT*
|
|
||||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
, const dummyT
|
|
||||||
#endif
|
|
||||||
>::type const_reverse_iterator;
|
|
||||||
|
|
||||||
const_reverse_iterator j(reversed + N);
|
|
||||||
boost::random_access_iterator_test(j, N, array);
|
|
||||||
|
|
||||||
const dummyT* const_reversed = reversed;
|
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
boost::const_nonconst_iterator_test(i, ++j);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test reverse_iterator_generator again, with traits fully deducible on all platforms
|
|
||||||
{
|
|
||||||
std::deque<dummyT> reversed_container;
|
|
||||||
std::reverse_copy(array, array + N, std::back_inserter(reversed_container));
|
|
||||||
const std::deque<dummyT>::iterator reversed = reversed_container.begin();
|
|
||||||
|
|
||||||
|
|
||||||
typedef boost::reverse_iterator_generator<
|
|
||||||
std::deque<dummyT>::iterator>::type reverse_iterator;
|
|
||||||
typedef boost::reverse_iterator_generator<
|
|
||||||
std::deque<dummyT>::const_iterator, const dummyT>::type const_reverse_iterator;
|
|
||||||
|
|
||||||
// MSVC/STLport gives an INTERNAL COMPILER ERROR when any computation
|
|
||||||
// (e.g. "reversed + N") is used in the constructor below.
|
|
||||||
const std::deque<dummyT>::iterator finish = reversed_container.end();
|
|
||||||
reverse_iterator i(finish);
|
|
||||||
|
|
||||||
boost::random_access_iterator_test(i, N, array);
|
|
||||||
boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
|
|
||||||
|
|
||||||
const_reverse_iterator j = reverse_iterator(finish);
|
|
||||||
boost::random_access_iterator_test(j, N, array);
|
|
||||||
|
|
||||||
const std::deque<dummyT>::const_iterator const_reversed = reversed;
|
|
||||||
boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
|
|
||||||
|
|
||||||
// Many compilers' builtin deque iterators don't interoperate well, though
|
|
||||||
// STLport fixes that problem.
|
|
||||||
#if defined(__SGI_STL_PORT) || !defined(__GNUC__) && !defined(__BORLANDC__) && !defined(BOOST_MSVC)
|
|
||||||
boost::const_nonconst_iterator_test(i, ++j);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test filter iterator
|
|
||||||
{
|
|
||||||
// Using typedefs for filter_gen::type and filter_gen::policies_type
|
|
||||||
// confused Borland terribly.
|
|
||||||
typedef boost::detail::non_bidirectional_category<dummyT*>::type category;
|
|
||||||
|
|
||||||
typedef ::boost::filter_iterator_generator<one_or_four, dummyT*
|
|
||||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
, dummyT
|
|
||||||
#endif
|
|
||||||
>::type filter_iter;
|
|
||||||
|
|
||||||
filter_iter i(array, filter_iter::policies_type(one_or_four(), array + N));
|
|
||||||
boost::forward_iterator_test(i, dummyT(1), dummyT(4));
|
|
||||||
|
|
||||||
enum { is_forward = boost::is_same<
|
|
||||||
filter_iter::iterator_category,
|
|
||||||
std::forward_iterator_tag>::value };
|
|
||||||
BOOST_STATIC_ASSERT(is_forward);
|
|
||||||
|
|
||||||
// On compilers not supporting partial specialization, we can do more type
|
|
||||||
// deduction with deque iterators than with pointers... unless the library
|
|
||||||
// is broken ;-(
|
|
||||||
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT)
|
|
||||||
std::deque<dummyT> array2;
|
|
||||||
std::copy(array+0, array+N, std::back_inserter(array2));
|
|
||||||
boost::forward_iterator_test(
|
|
||||||
boost::make_filter_iterator(array2.begin(), array2.end(), one_or_four()),
|
|
||||||
dummyT(1), dummyT(4));
|
|
||||||
|
|
||||||
boost::forward_iterator_test(
|
|
||||||
boost::make_filter_iterator<one_or_four>(array2.begin(), array2.end()),
|
|
||||||
dummyT(1), dummyT(4));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(BOOST_MSVC) // This just freaks MSVC out completely
|
|
||||||
boost::forward_iterator_test(
|
|
||||||
boost::make_filter_iterator<one_or_four>(
|
|
||||||
boost::make_reverse_iterator(array2.end()),
|
|
||||||
boost::make_reverse_iterator(array2.begin())
|
|
||||||
),
|
|
||||||
dummyT(4), dummyT(1));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
boost::forward_iterator_test(
|
|
||||||
boost::make_filter_iterator(array+0, array+N, one_or_four()),
|
|
||||||
dummyT(1), dummyT(4));
|
|
||||||
|
|
||||||
boost::forward_iterator_test(
|
|
||||||
boost::make_filter_iterator<one_or_four>(array, array + N),
|
|
||||||
dummyT(1), dummyT(4));
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// check operator-> with a forward iterator
|
|
||||||
{
|
|
||||||
boost::forward_iterator_archetype<dummyT> forward_iter;
|
|
||||||
typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
|
|
||||||
boost::default_iterator_policies,
|
|
||||||
dummyT, const dummyT&, const dummyT*,
|
|
||||||
std::forward_iterator_tag, std::ptrdiff_t> adaptor_type;
|
|
||||||
adaptor_type i(forward_iter);
|
|
||||||
if (0) // don't do this, just make sure it compiles
|
|
||||||
assert((*i).m_x == i->foo());
|
|
||||||
}
|
|
||||||
// check operator-> with an input iterator
|
|
||||||
{
|
|
||||||
boost::input_iterator_archetype<dummyT> input_iter;
|
|
||||||
typedef boost::iterator_adaptor<boost::input_iterator_archetype<dummyT>,
|
|
||||||
boost::default_iterator_policies,
|
|
||||||
dummyT, const dummyT&, const dummyT*,
|
|
||||||
std::input_iterator_tag, std::ptrdiff_t> adaptor_type;
|
|
||||||
adaptor_type i(input_iter);
|
|
||||||
if (0) // don't do this, just make sure it compiles
|
|
||||||
assert((*i).m_x == i->foo());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "test successful " << std::endl;
|
|
||||||
return 0;
|
|
||||||
}
|
|
96
projection_iterator_example.cpp
Normal file
96
projection_iterator_example.cpp
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
// (C) Copyright Jeremy Siek 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.
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <list>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
#include <boost/iterator_adaptors.hpp>
|
||||||
|
|
||||||
|
struct personnel_record {
|
||||||
|
personnel_record(std::string n, int id) : m_name(n), m_ID(id) { }
|
||||||
|
std::string m_name;
|
||||||
|
int m_ID;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct select_name {
|
||||||
|
typedef personnel_record argument_type;
|
||||||
|
typedef std::string result_type;
|
||||||
|
const std::string& operator()(const personnel_record& r) const {
|
||||||
|
return r.m_name;
|
||||||
|
}
|
||||||
|
std::string& operator()(personnel_record& r) const {
|
||||||
|
return r.m_name;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct select_ID {
|
||||||
|
typedef personnel_record argument_type;
|
||||||
|
typedef int result_type;
|
||||||
|
const int& operator()(const personnel_record& r) const {
|
||||||
|
return r.m_ID;
|
||||||
|
}
|
||||||
|
int& operator()(personnel_record& r) const {
|
||||||
|
return r.m_ID;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int, char*[])
|
||||||
|
{
|
||||||
|
std::list<personnel_record> personnel_list;
|
||||||
|
|
||||||
|
personnel_list.push_back(personnel_record("Barney", 13423));
|
||||||
|
personnel_list.push_back(personnel_record("Fred", 12343));
|
||||||
|
personnel_list.push_back(personnel_record("Wilma", 62454));
|
||||||
|
personnel_list.push_back(personnel_record("Betty", 20490));
|
||||||
|
|
||||||
|
// Example of using projection_iterator_generator
|
||||||
|
// to print out the names in the personnel list.
|
||||||
|
|
||||||
|
boost::projection_iterator_generator<select_name,
|
||||||
|
std::list<personnel_record>::iterator>::type
|
||||||
|
personnel_first(personnel_list.begin()),
|
||||||
|
personnel_last(personnel_list.end());
|
||||||
|
|
||||||
|
std::copy(personnel_first, personnel_last,
|
||||||
|
std::ostream_iterator<std::string>(std::cout, "\n"));
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
// Example of using projection_iterator_pair_generator
|
||||||
|
// to assign new ID numbers to the personnel.
|
||||||
|
|
||||||
|
typedef boost::projection_iterator_pair_generator<select_ID,
|
||||||
|
std::list<personnel_record>::iterator,
|
||||||
|
std::list<personnel_record>::const_iterator> PairGen;
|
||||||
|
|
||||||
|
PairGen::iterator ID_first(personnel_list.begin()),
|
||||||
|
ID_last(personnel_list.end());
|
||||||
|
|
||||||
|
int new_id = 0;
|
||||||
|
while (ID_first != ID_last) {
|
||||||
|
*ID_first = new_id++;
|
||||||
|
++ID_first;
|
||||||
|
}
|
||||||
|
|
||||||
|
PairGen::const_iterator const_ID_first(personnel_list.begin()),
|
||||||
|
const_ID_last(personnel_list.end());
|
||||||
|
|
||||||
|
std::copy(const_ID_first, const_ID_last,
|
||||||
|
std::ostream_iterator<int>(std::cout, " "));
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
// Example of using make_const_projection_iterator()
|
||||||
|
// to print out the names in the personnel list again.
|
||||||
|
|
||||||
|
std::copy
|
||||||
|
(boost::make_const_projection_iterator<select_name>(personnel_list.begin()),
|
||||||
|
boost::make_const_projection_iterator<select_name>(personnel_list.end()),
|
||||||
|
std::ostream_iterator<std::string>(std::cout, "\n"));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
42
reverse_iterator_example.cpp
Normal file
42
reverse_iterator_example.cpp
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// (C) Copyright Jeremy Siek 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.
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <boost/iterator_adaptors.hpp>
|
||||||
|
|
||||||
|
int main(int, char*[])
|
||||||
|
{
|
||||||
|
char letters[] = "hello world!";
|
||||||
|
const int N = sizeof(letters)/sizeof(char) - 1;
|
||||||
|
std::cout << "original sequence of letters:\t"
|
||||||
|
<< letters << std::endl;
|
||||||
|
|
||||||
|
std::sort(letters, letters + N);
|
||||||
|
|
||||||
|
// Use reverse_iterator_generator to print a sequence
|
||||||
|
// of letters in reverse order.
|
||||||
|
|
||||||
|
boost::reverse_iterator_generator<char*>::type
|
||||||
|
reverse_letters_first(letters + N),
|
||||||
|
reverse_letters_last(letters);
|
||||||
|
|
||||||
|
std::cout << "letters in descending order:\t";
|
||||||
|
std::copy(reverse_letters_first, reverse_letters_last,
|
||||||
|
std::ostream_iterator<char>(std::cout));
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
// Use make_reverse_iterator() to print the sequence
|
||||||
|
// of letters in reverse-reverse order.
|
||||||
|
|
||||||
|
std::cout << "letters in ascending order:\t";
|
||||||
|
std::copy(boost::make_reverse_iterator(reverse_letters_last),
|
||||||
|
boost::make_reverse_iterator(reverse_letters_first),
|
||||||
|
std::ostream_iterator<char>(std::cout));
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
44
transform_iterator_example.cpp
Normal file
44
transform_iterator_example.cpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
// (C) Copyright Jeremy Siek 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.
|
||||||
|
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <boost/iterator_adaptors.hpp>
|
||||||
|
|
||||||
|
int
|
||||||
|
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 };
|
||||||
|
const int N = sizeof(x)/sizeof(int);
|
||||||
|
|
||||||
|
typedef std::binder1st< std::multiplies<int> > Function;
|
||||||
|
typedef boost::transform_iterator_generator<Function, int*>::type doubling_iterator;
|
||||||
|
|
||||||
|
doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)),
|
||||||
|
i_end(x + N, std::bind1st(std::multiplies<int>(), 2));
|
||||||
|
|
||||||
|
std::cout << "multiplying the array by 2:" << std::endl;
|
||||||
|
while (i != i_end)
|
||||||
|
std::cout << *i++ << " ";
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
std::cout << "adding 4 to each element in the array:" << std::endl;
|
||||||
|
|
||||||
|
std::copy(boost::make_transform_iterator(x, std::bind1st(std::plus<int>(), 4)),
|
||||||
|
boost::make_transform_iterator(x + N, std::bind1st(std::plus<int>(), 4)),
|
||||||
|
std::ostream_iterator<int>(std::cout, " "));
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user