mirror of
https://github.com/boostorg/utility.git
synced 2025-10-10 23:55:20 +02:00
Compare commits
1 Commits
boost-1.20
...
boost-1.19
Author | SHA1 | Date | |
---|---|---|---|
|
566ba3a832 |
148
cast.htm
Normal file
148
cast.htm
Normal 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 <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 "The C++
|
||||||
|
Programming Language".<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. Downcasting means
|
||||||
|
casting from a base class to a derived class. 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. 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. <b> </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. 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. It must also be used for crosscasts. It does an assert(
|
||||||
|
dynamic_cast<Derived>(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. 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 <class Derived, class Base>
|
||||||
|
inline Derived polymorphic_cast(Base* x);
|
||||||
|
// Throws: std::bad_cast if ( dynamic_cast<Derived>(x) == 0 )
|
||||||
|
// Returns: dynamic_cast<Derived>(x)
|
||||||
|
|
||||||
|
template <class Derived, class Base>
|
||||||
|
inline Derived polymorphic_downcast(Base* x);
|
||||||
|
// Effects: assert( dynamic_cast<Derived>(x) == x );
|
||||||
|
// Returns: static_cast<Derived>(x)</pre>
|
||||||
|
</blockquote>
|
||||||
|
<h3>polymorphic_downcast example</h3>
|
||||||
|
<blockquote>
|
||||||
|
<pre>#include <boost/cast.hpp>
|
||||||
|
...
|
||||||
|
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<Banana*>(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<>::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<typename Target, typename Source>
|
||||||
|
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<Target>(arg)</pre>
|
||||||
|
</blockquote>
|
||||||
|
<h3>numeric_cast example</h3>
|
||||||
|
<blockquote>
|
||||||
|
<pre>#include <boost/cast.hpp>
|
||||||
|
using namespace boost::cast;
|
||||||
|
|
||||||
|
void ariane(double vx)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
unsigned short dx = numeric_cast<unsigned short>(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 <!--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 "as is" 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
153
cast_test.cpp
Normal 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
|
@@ -78,9 +78,6 @@ int main()
|
|||||||
compressed_pair<non_empty1, non_empty2> cp1d(non_empty2(9));
|
compressed_pair<non_empty1, non_empty2> cp1d(non_empty2(9));
|
||||||
assert(cp1d.second() == non_empty2(9));
|
assert(cp1d.second() == non_empty2(9));
|
||||||
assert(cp1d.first() == non_empty1());
|
assert(cp1d.first() == non_empty1());
|
||||||
|
|
||||||
compressed_pair<int, double> cp1e(cp1);
|
|
||||||
|
|
||||||
compressed_pair<empty_UDT, int> cp2(2);
|
compressed_pair<empty_UDT, int> cp2(2);
|
||||||
assert(cp2.second() == 2);
|
assert(cp2.second() == 2);
|
||||||
compressed_pair<int, empty_UDT> cp3(1);
|
compressed_pair<int, empty_UDT> cp3(1);
|
||||||
|
@@ -1,189 +0,0 @@
|
|||||||
// (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
|
|
||||||
// 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 <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);
|
|
||||||
|
|
||||||
test(static_cast<typename Container::const_iterator>(start),
|
|
||||||
static_cast<typename Container::const_iterator>(finish));
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
// 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));
|
|
||||||
return 0;
|
|
||||||
}
|
|
@@ -1,367 +0,0 @@
|
|||||||
// (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
|
|
||||||
// 29 Jan 2001 Initial revision (David Abrahams)
|
|
||||||
|
|
||||||
#include <boost/half_open_range.hpp>
|
|
||||||
#include <boost/utility.hpp>
|
|
||||||
#include <iterator>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
#include <cassert>
|
|
||||||
#include <stdexcept>
|
|
||||||
#ifndef BOOST_NO_LIMITS
|
|
||||||
# include <limits>
|
|
||||||
#endif
|
|
||||||
#ifndef BOOST_NO_SLIST
|
|
||||||
# include <slist>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
inline unsigned unsigned_random(unsigned max)
|
|
||||||
{
|
|
||||||
return (max > 0) ? (unsigned)rand() % max : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special tests for ranges supporting random access
|
|
||||||
template <class T>
|
|
||||||
void category_test_1(
|
|
||||||
const boost::half_open_range<T>& r, std::random_access_iterator_tag)
|
|
||||||
{
|
|
||||||
typedef boost::half_open_range<T> range;
|
|
||||||
typedef typename range::size_type size_type;
|
|
||||||
size_type size = r.size();
|
|
||||||
|
|
||||||
// pick a random offset
|
|
||||||
size_type offset = unsigned_random(size);
|
|
||||||
|
|
||||||
typename range::value_type x = *(r.begin() + offset);
|
|
||||||
// test contains(value_type)
|
|
||||||
assert(r.contains(r.start()) == !r.empty());
|
|
||||||
assert(!r.contains(r.finish()));
|
|
||||||
assert(r.contains(x) == (offset != size));
|
|
||||||
|
|
||||||
range::const_iterator p = r.find(x);
|
|
||||||
assert((p == r.end()) == (x == r.finish()));
|
|
||||||
assert(r.find(r.finish()) == r.end());
|
|
||||||
|
|
||||||
if (offset != size)
|
|
||||||
{
|
|
||||||
assert(x == r[offset]);
|
|
||||||
assert(x == r.at(offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool caught_out_of_range = false;
|
|
||||||
try {
|
|
||||||
bool never_initialized = x == r.at(size);
|
|
||||||
(void)never_initialized;
|
|
||||||
}
|
|
||||||
catch(std::out_of_range&)
|
|
||||||
{
|
|
||||||
caught_out_of_range = true;
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
assert(caught_out_of_range);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Those tests must be skipped for other ranges
|
|
||||||
template <class T>
|
|
||||||
void category_test_1(
|
|
||||||
const boost::half_open_range<T>&, std::forward_iterator_tag)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned indices[][2] = { {0,0},{0,1},{0,2},{0,3},
|
|
||||||
{1,1},{1,2},{1,3},
|
|
||||||
{2,2},{2,3},
|
|
||||||
{3,3}};
|
|
||||||
|
|
||||||
template <class Range>
|
|
||||||
void category_test_2(
|
|
||||||
const std::vector<Range>& ranges, unsigned i, unsigned j, std::random_access_iterator_tag)
|
|
||||||
{
|
|
||||||
typedef Range range;
|
|
||||||
const range& ri = ranges[i];
|
|
||||||
const range& rj = ranges[j];
|
|
||||||
|
|
||||||
if (indices[i][0] <= indices[j][0] && indices[i][1] >= indices[j][1])
|
|
||||||
assert(ri.contains(rj));
|
|
||||||
|
|
||||||
if (ri.contains(rj))
|
|
||||||
assert((ri & rj) == rj);
|
|
||||||
assert(boost::intersects(ri, rj) == !(ri & rj).empty());
|
|
||||||
|
|
||||||
range t1(ri);
|
|
||||||
t1 &= rj;
|
|
||||||
assert(t1 == range(indices[i][0] > indices[j][0] ? ri.start() : rj.start(),
|
|
||||||
indices[i][1] < indices[j][1] ? ri.finish() : rj.finish()));
|
|
||||||
assert(t1 == (ri & rj));
|
|
||||||
|
|
||||||
range t2(ri);
|
|
||||||
t2 |= rj;
|
|
||||||
|
|
||||||
if (ri.empty())
|
|
||||||
assert(t2 == rj);
|
|
||||||
else if (rj.empty())
|
|
||||||
assert(t2 == ri);
|
|
||||||
else
|
|
||||||
assert(t2 == range(indices[i][0] < indices[j][0] ? ri.start() : rj.start(),
|
|
||||||
indices[i][1] > indices[j][1] ? ri.finish() : rj.finish()));
|
|
||||||
assert(t2 == (ri | rj));
|
|
||||||
if (i == j)
|
|
||||||
assert(ri == rj);
|
|
||||||
|
|
||||||
if (ri.empty() || rj.empty())
|
|
||||||
assert((ri == rj) == (ri.empty() && rj.empty()));
|
|
||||||
else
|
|
||||||
assert((ri == rj) == (ri.start() == rj.start() && ri.finish() == rj.finish()));
|
|
||||||
|
|
||||||
assert((ri == rj) == !(ri != rj));
|
|
||||||
|
|
||||||
bool same = ri == rj;
|
|
||||||
bool one_empty = ri.empty() != rj.empty();
|
|
||||||
|
|
||||||
std::less<range> less;
|
|
||||||
std::less_equal<range> less_equal;
|
|
||||||
std::greater<range> greater;
|
|
||||||
std::greater_equal<range> greater_equal;
|
|
||||||
|
|
||||||
if (same)
|
|
||||||
{
|
|
||||||
assert(greater_equal(ri,rj));
|
|
||||||
assert(less_equal(ri,rj));
|
|
||||||
assert(!greater(ri,rj));
|
|
||||||
assert(!less(ri,rj));
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
else if (one_empty)
|
|
||||||
{
|
|
||||||
const range& empty = ri.empty() ? ri : rj;
|
|
||||||
const range& non_empty = rj.empty() ? ri : rj;
|
|
||||||
|
|
||||||
assert(less(empty,non_empty));
|
|
||||||
assert(less_equal(empty,non_empty));
|
|
||||||
assert(!greater(empty,non_empty));
|
|
||||||
assert(!greater_equal(empty,non_empty));
|
|
||||||
assert(!less(non_empty,empty));
|
|
||||||
assert(!less_equal(non_empty,empty));
|
|
||||||
assert(greater(non_empty,empty));
|
|
||||||
assert(greater_equal(non_empty,empty));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (indices[i][0] < indices[j][0] ||
|
|
||||||
indices[i][0] == indices[j][0] && indices[i][1] < indices[j][1])
|
|
||||||
{
|
|
||||||
assert(!greater_equal(ri,rj));
|
|
||||||
assert(less(ri,rj));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (indices[i][0] < indices[j][0] ||
|
|
||||||
indices[i][0] == indices[j][0] && indices[i][1] <= indices[j][1])
|
|
||||||
{
|
|
||||||
assert(!greater(ri,rj));
|
|
||||||
assert(less_equal(ri,rj));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (indices[i][0] > indices[j][0] ||
|
|
||||||
indices[i][0] == indices[j][0] && indices[i][1] > indices[j][1])
|
|
||||||
{
|
|
||||||
assert(!less_equal(ri,rj));
|
|
||||||
assert(greater(ri,rj));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (indices[i][0] > indices[j][0] ||
|
|
||||||
indices[i][0] == indices[j][0] && indices[i][1] >= indices[j][1])
|
|
||||||
{
|
|
||||||
assert(!less(ri,rj));
|
|
||||||
assert(greater_equal(ri,rj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <class Range>
|
|
||||||
void category_test_2(
|
|
||||||
const std::vector<Range>&, unsigned, unsigned, std::forward_iterator_tag)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void category_test_2(
|
|
||||||
const std::vector<boost::half_open_range<T> >&, unsigned, unsigned, std::bidirectional_iterator_tag)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Range>
|
|
||||||
void test_back(Range& x, std::bidirectional_iterator_tag)
|
|
||||||
{
|
|
||||||
assert(x.back() == boost::prior(x.finish()));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Range>
|
|
||||||
void test_back(Range& x, std::forward_iterator_tag)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
boost::half_open_range<T> range_identity(const boost::half_open_range<T>& x)
|
|
||||||
{
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void test(T x0, T x1, T x2, T x3)
|
|
||||||
{
|
|
||||||
std::vector<boost::half_open_range<T> > ranges;
|
|
||||||
typedef boost::half_open_range<T> range;
|
|
||||||
|
|
||||||
T bounds[4] = { x0, x1, x2, x3 };
|
|
||||||
|
|
||||||
const std::size_t num_ranges = sizeof(indices)/sizeof(*indices);
|
|
||||||
// test construction
|
|
||||||
for (std::size_t n = 0; n < num_ranges;++n)
|
|
||||||
{
|
|
||||||
T start = bounds[indices[n][0]];
|
|
||||||
T finish = bounds[indices[n][1]];
|
|
||||||
boost::half_open_range<T> r(start, finish);
|
|
||||||
ranges.push_back(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
// test implicit conversion from std::pair<T,T>
|
|
||||||
range converted = std::pair<T,T>(x0,x0);
|
|
||||||
(void)converted;
|
|
||||||
|
|
||||||
// test assignment, equality and inequality
|
|
||||||
range r00 = range(x0, x0);
|
|
||||||
assert(r00 == range(x0,x0));
|
|
||||||
assert(r00 == range(x1,x1)); // empty ranges are all equal
|
|
||||||
if (x3 != x0)
|
|
||||||
assert(r00 != range(x0, x3));
|
|
||||||
r00 = range(x0, x3);
|
|
||||||
assert(r00 == range(x0, x3));
|
|
||||||
if (x3 != x0)
|
|
||||||
assert(r00 != range(x0, x0));
|
|
||||||
|
|
||||||
typedef typename range::iterator iterator;
|
|
||||||
typedef typename iterator::iterator_category category;
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < num_ranges; ++i)
|
|
||||||
{
|
|
||||||
const range& r = ranges[i];
|
|
||||||
|
|
||||||
// test begin(), end(), basic iteration.
|
|
||||||
unsigned count = 0;
|
|
||||||
for (range::const_iterator p = r.begin(), finish = r.end();
|
|
||||||
p != finish;
|
|
||||||
++p, ++count)
|
|
||||||
{
|
|
||||||
assert(count < 2100);
|
|
||||||
}
|
|
||||||
|
|
||||||
// test size(), empty(), front(), back()
|
|
||||||
assert((unsigned)r.size() == count);
|
|
||||||
if (indices[i][0] == indices[i][1])
|
|
||||||
assert(r.empty());
|
|
||||||
if (r.empty())
|
|
||||||
assert(r.size() == 0);
|
|
||||||
if (!r.empty())
|
|
||||||
{
|
|
||||||
assert(r.front() == r.start());
|
|
||||||
test_back(r, category());
|
|
||||||
}
|
|
||||||
|
|
||||||
// test swap
|
|
||||||
range r1(r);
|
|
||||||
range r2(x0,x3);
|
|
||||||
const bool same = r1 == r2;
|
|
||||||
r1.swap(r2);
|
|
||||||
assert(r1 == range(x0,x3));
|
|
||||||
assert(r2 == r);
|
|
||||||
if (!same) {
|
|
||||||
assert(r1 != r);
|
|
||||||
assert(r2 != range(x0,x3));
|
|
||||||
}
|
|
||||||
|
|
||||||
// do individual tests for random-access iterators
|
|
||||||
category_test_1(r, category());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned j = 0; j < num_ranges; ++j) {
|
|
||||||
for (unsigned k = 0; k < num_ranges; ++k) {
|
|
||||||
category_test_2(ranges, j, k, category());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Integer>
|
|
||||||
void test_integer(Integer* = 0) // default arg works around MSVC bug
|
|
||||||
{
|
|
||||||
const Integer a = 0;
|
|
||||||
const Integer b = a + unsigned_random(128 - a);
|
|
||||||
const Integer c = b + unsigned_random(128 - b);
|
|
||||||
const Integer d = c + unsigned_random(128 - c);
|
|
||||||
|
|
||||||
test(a, b, c, d);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Container>
|
|
||||||
void test_container(Container* = 0) // default arg works around MSVC bug
|
|
||||||
{
|
|
||||||
Container c(unsigned_random(1673));
|
|
||||||
|
|
||||||
const typename Container::size_type offset1 = unsigned_random(c.size());
|
|
||||||
const typename Container::size_type offset2 = unsigned_random(c.size() - offset1);
|
|
||||||
typename Container::iterator internal1 = c.begin();
|
|
||||||
std::advance(internal1, offset1);
|
|
||||||
typename Container::iterator internal2 = internal1;
|
|
||||||
std::advance(internal2, offset2);
|
|
||||||
|
|
||||||
test(c.begin(), internal1, internal2, c.end());
|
|
||||||
|
|
||||||
typedef typename Container::const_iterator const_iterator;
|
|
||||||
test(const_iterator(c.begin()),
|
|
||||||
const_iterator(internal1),
|
|
||||||
const_iterator(internal2),
|
|
||||||
const_iterator(c.end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
// 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];
|
|
||||||
const std::size_t a = 0;
|
|
||||||
const std::size_t b = a + unsigned_random(2000 - a);
|
|
||||||
const std::size_t c = b + unsigned_random(2000 - b);
|
|
||||||
test(array, array+b, array+c, array+2000);
|
|
||||||
return 0;
|
|
||||||
}
|
|
@@ -8,8 +8,6 @@
|
|||||||
// see libs/utility/compressed_pair.hpp
|
// see libs/utility/compressed_pair.hpp
|
||||||
//
|
//
|
||||||
/* Release notes:
|
/* Release notes:
|
||||||
20 Jan 2001:
|
|
||||||
Fixed obvious bugs (David Abrahams)
|
|
||||||
07 Oct 2000:
|
07 Oct 2000:
|
||||||
Added better single argument constructor support.
|
Added better single argument constructor support.
|
||||||
03 Oct 2000:
|
03 Oct 2000:
|
||||||
@@ -44,14 +42,10 @@ namespace boost
|
|||||||
// have one template single-argument constructor
|
// have one template single-argument constructor
|
||||||
// in place of two specific constructors:
|
// in place of two specific constructors:
|
||||||
//
|
//
|
||||||
|
|
||||||
template <class T1, class T2>
|
|
||||||
class compressed_pair;
|
|
||||||
|
|
||||||
namespace detail{
|
namespace detail{
|
||||||
|
|
||||||
template <class A, class T1, class T2>
|
template <class A, class T1, class T2>
|
||||||
struct best_conversion_traits
|
struct best_convertion_traits
|
||||||
{
|
{
|
||||||
typedef char one;
|
typedef char one;
|
||||||
typedef char (&two)[2];
|
typedef char (&two)[2];
|
||||||
@@ -108,20 +102,8 @@ public:
|
|||||||
template <class A>
|
template <class A>
|
||||||
explicit compressed_pair_0(const A& val)
|
explicit compressed_pair_0(const A& val)
|
||||||
{
|
{
|
||||||
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, &_second);
|
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()) {}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
compressed_pair_0& operator=(const compressed_pair_0& x) {
|
|
||||||
cout << "assigning compressed pair 0" << endl;
|
|
||||||
_first = x._first;
|
|
||||||
_second = x._second;
|
|
||||||
cout << "finished assigning compressed pair 0" << endl;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
first_reference first() { return _first; }
|
first_reference first() { return _first; }
|
||||||
first_const_reference first() const { return _first; }
|
first_const_reference first() const { return _first; }
|
||||||
@@ -155,27 +137,12 @@ public:
|
|||||||
|
|
||||||
compressed_pair_1() : T2(), _first() {}
|
compressed_pair_1() : T2(), _first() {}
|
||||||
compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {}
|
compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {}
|
||||||
|
|
||||||
template <class A>
|
template <class A>
|
||||||
explicit compressed_pair_1(const A& val)
|
explicit compressed_pair_1(const A& val)
|
||||||
{
|
{
|
||||||
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, static_cast<T2*>(this));
|
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.second()), _first(x.first()) {}
|
|
||||||
|
|
||||||
#ifdef BOOST_MSVC
|
|
||||||
// Total weirdness. If the assignment to _first is moved after
|
|
||||||
// the call to the inherited operator=, then this breaks graph/test/graph.cpp
|
|
||||||
// by way of iterator_adaptor.
|
|
||||||
compressed_pair_1& operator=(const compressed_pair_1& x) {
|
|
||||||
_first = x._first;
|
|
||||||
T2::operator=(x);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
first_reference first() { return _first; }
|
first_reference first() { return _first; }
|
||||||
first_const_reference first() const { return _first; }
|
first_const_reference first() const { return _first; }
|
||||||
|
|
||||||
@@ -211,20 +178,9 @@ public:
|
|||||||
template <class A>
|
template <class A>
|
||||||
explicit compressed_pair_2(const A& val)
|
explicit compressed_pair_2(const A& val)
|
||||||
{
|
{
|
||||||
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), &_second);
|
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.first()), _second(x.second()) {}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
compressed_pair_2& operator=(const compressed_pair_2& x) {
|
|
||||||
cout << "assigning compressed pair 2" << endl;
|
|
||||||
T1::operator=(x);
|
|
||||||
_second = x._second;
|
|
||||||
cout << "finished assigning compressed pair 2" << endl;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
first_reference first() { return *this; }
|
first_reference first() { return *this; }
|
||||||
first_const_reference first() const { return *this; }
|
first_const_reference first() const { return *this; }
|
||||||
|
|
||||||
@@ -258,10 +214,8 @@ public:
|
|||||||
template <class A>
|
template <class A>
|
||||||
explicit compressed_pair_3(const A& val)
|
explicit compressed_pair_3(const A& val)
|
||||||
{
|
{
|
||||||
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), static_cast<T2*>(this));
|
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.first()), T2(x.second()) {}
|
|
||||||
|
|
||||||
first_reference first() { return *this; }
|
first_reference first() { return *this; }
|
||||||
first_const_reference first() const { return *this; }
|
first_const_reference first() const { return *this; }
|
||||||
@@ -293,8 +247,6 @@ public:
|
|||||||
compressed_pair_4(first_param_type x, second_param_type) : T1(x) {}
|
compressed_pair_4(first_param_type x, second_param_type) : T1(x) {}
|
||||||
// only one single argument constructor since T1 == T2
|
// only one single argument constructor since T1 == T2
|
||||||
explicit compressed_pair_4(first_param_type x) : T1(x) {}
|
explicit compressed_pair_4(first_param_type x) : T1(x) {}
|
||||||
compressed_pair_4(const ::boost::compressed_pair<T1,T2>& x)
|
|
||||||
: T1(x.first()){}
|
|
||||||
|
|
||||||
first_reference first() { return *this; }
|
first_reference first() { return *this; }
|
||||||
first_const_reference first() const { return *this; }
|
first_const_reference first() const { return *this; }
|
||||||
@@ -328,9 +280,7 @@ public:
|
|||||||
compressed_pair_5() : _first(), _second() {}
|
compressed_pair_5() : _first(), _second() {}
|
||||||
compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {}
|
compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {}
|
||||||
// only one single argument constructor since T1 == T2
|
// only one single argument constructor since T1 == T2
|
||||||
explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {}
|
explicit compressed_pair_5(first_param_type x) : _first(x), _second() {}
|
||||||
compressed_pair_5(const ::boost::compressed_pair<T1,T2>& c)
|
|
||||||
: _first(c.first()), _second(c.second()) {}
|
|
||||||
|
|
||||||
first_reference first() { return _first; }
|
first_reference first() { return _first; }
|
||||||
first_const_reference first() const { return _first; }
|
first_const_reference first() const { return _first; }
|
||||||
@@ -503,4 +453,3 @@ inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
|
|||||||
#endif // BOOST_OB_COMPRESSED_PAIR_HPP
|
#endif // BOOST_OB_COMPRESSED_PAIR_HPP
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,27 +0,0 @@
|
|||||||
// 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 <list>
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
#include <boost/pending/iterator_adaptors.hpp>
|
|
||||||
#include <boost/detail/iterator.hpp>
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies,
|
|
||||||
boost::iterator<std::bidirectional_iterator_tag, int> > adaptor_type;
|
|
||||||
|
|
||||||
adaptor_type i;
|
|
||||||
i += 4;
|
|
||||||
return 0;
|
|
||||||
}
|
|
@@ -1,28 +0,0 @@
|
|||||||
// 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 <iostream>
|
|
||||||
#include <iterator>
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
#include <boost/pending/iterator_adaptors.hpp>
|
|
||||||
#include <boost/detail/iterator.hpp>
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies,
|
|
||||||
boost::iterator<std::input_iterator_tag, int> > adaptor_type;
|
|
||||||
|
|
||||||
adaptor_type iter;
|
|
||||||
--iter;
|
|
||||||
return 0;
|
|
||||||
}
|
|
@@ -1,32 +0,0 @@
|
|||||||
// 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 <list>
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
#include <boost/pending/iterator_adaptors.hpp>
|
|
||||||
#include <boost/detail/iterator.hpp>
|
|
||||||
|
|
||||||
class foo {
|
|
||||||
public:
|
|
||||||
void bar() { }
|
|
||||||
};
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
typedef boost::iterator_adaptor<foo*, boost::default_iterator_policies,
|
|
||||||
boost::iterator<std::input_iterator_tag, foo> > adaptor_type;
|
|
||||||
|
|
||||||
adaptor_type i;
|
|
||||||
i->bar();
|
|
||||||
return 0;
|
|
||||||
}
|
|
@@ -9,26 +9,6 @@
|
|||||||
// See http://www.boost.org for most recent version including documentation.
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
|
||||||
// Revision History
|
// Revision History
|
||||||
// 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)
|
// 13 Jun 00 Added const version of the iterator tests (Jeremy Siek)
|
||||||
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
|
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
|
||||||
|
|
||||||
@@ -37,17 +17,13 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <boost/pending/iterator_adaptors.hpp>
|
||||||
#include <boost/iterator_adaptors.hpp>
|
|
||||||
#include <boost/pending/iterator_tests.hpp>
|
#include <boost/pending/iterator_tests.hpp>
|
||||||
#include <boost/pending/integer_range.hpp>
|
#include <boost/pending/integer_range.hpp>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <deque>
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
struct my_iterator_tag : public std::random_access_iterator_tag { };
|
struct my_iterator_tag : public std::random_access_iterator_tag { };
|
||||||
|
|
||||||
|
|
||||||
using boost::dummyT;
|
using boost::dummyT;
|
||||||
|
|
||||||
struct my_iter_traits {
|
struct my_iter_traits {
|
||||||
@@ -66,12 +42,9 @@ struct my_const_iter_traits {
|
|||||||
typedef std::ptrdiff_t difference_type;
|
typedef std::ptrdiff_t difference_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef boost::iterator_adaptor<dummyT*,
|
typedef boost::iterator_adaptors
|
||||||
boost::default_iterator_policies, my_iter_traits> my_iterator;
|
<dummyT*, const dummyT*,
|
||||||
|
my_iter_traits, my_const_iter_traits> My;
|
||||||
typedef boost::iterator_adaptor<const dummyT*,
|
|
||||||
boost::default_iterator_policies, my_const_iter_traits> const_my_iterator;
|
|
||||||
|
|
||||||
|
|
||||||
struct mult_functor {
|
struct mult_functor {
|
||||||
typedef int result_type;
|
typedef int result_type;
|
||||||
@@ -98,88 +71,6 @@ struct select1st_
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
@@ -190,21 +81,12 @@ main()
|
|||||||
// sanity check, if this doesn't pass the test is buggy
|
// sanity check, if this doesn't pass the test is buggy
|
||||||
boost::random_access_iterator_test(array,N,array);
|
boost::random_access_iterator_test(array,N,array);
|
||||||
|
|
||||||
// Check that the policy concept checks and the default policy
|
// Test the iterator_adaptors
|
||||||
// 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;
|
My::iterator i = array;
|
||||||
boost::random_access_iterator_test(i, N, array);
|
boost::random_access_iterator_test(i, N, array);
|
||||||
|
|
||||||
const_my_iterator j = array;
|
My::const_iterator j = array;
|
||||||
boost::random_access_iterator_test(j, N, array);
|
boost::random_access_iterator_test(j, N, array);
|
||||||
boost::const_nonconst_iterator_test(i, ++j);
|
boost::const_nonconst_iterator_test(i, ++j);
|
||||||
}
|
}
|
||||||
@@ -218,134 +100,69 @@ main()
|
|||||||
for (int k2 = 0; k2 < N; ++k2)
|
for (int k2 = 0; k2 < N; ++k2)
|
||||||
x[k2] = x[k2] * 2;
|
x[k2] = x[k2] * 2;
|
||||||
|
|
||||||
boost::transform_iterator_generator<mult_functor, int*>::type
|
boost::transform_iterator<mult_functor, int*,
|
||||||
|
boost::iterator<std::random_access_iterator_tag,int> >::type
|
||||||
i(y, mult_functor(2));
|
i(y, mult_functor(2));
|
||||||
boost::input_iterator_test(i, x[0], x[1]);
|
boost::random_access_iterator_test(i, N, x);
|
||||||
boost::input_iterator_test(boost::make_transform_iterator(&y[0], mult_functor(2)), x[0], x[1]);
|
|
||||||
}
|
}
|
||||||
|
// Test indirect_iterators
|
||||||
// Test indirect_iterator_generator
|
|
||||||
{
|
{
|
||||||
dummyT* ptr[N];
|
dummyT* ptr[N];
|
||||||
for (int k = 0; k < N; ++k)
|
for (int k = 0; k < N; ++k)
|
||||||
ptr[k] = array + k;
|
ptr[k] = array + k;
|
||||||
|
typedef boost::indirect_iterators<dummyT**, dummyT*, const dummyT*,
|
||||||
typedef boost::indirect_iterator_generator<dummyT**
|
boost::iterator<std::random_access_iterator_tag, dummyT*>,
|
||||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
boost::iterator<std::random_access_iterator_tag, dummyT>,
|
||||||
, dummyT
|
boost::iterator<std::random_access_iterator_tag, const dummyT>
|
||||||
#endif
|
> Indirect;
|
||||||
>::type indirect_iterator;
|
Indirect::iterator i = ptr;
|
||||||
|
|
||||||
typedef boost::indirect_iterator_generator<dummyT**, const dummyT>::type const_indirect_iterator;
|
|
||||||
|
|
||||||
indirect_iterator i = ptr;
|
|
||||||
boost::random_access_iterator_test(i, N, array);
|
boost::random_access_iterator_test(i, N, array);
|
||||||
|
|
||||||
boost::random_access_iterator_test(boost::make_indirect_iterator<dummyT>(ptr), N, array);
|
Indirect::const_iterator j = ptr;
|
||||||
|
|
||||||
const_indirect_iterator j = ptr;
|
|
||||||
boost::random_access_iterator_test(j, N, array);
|
boost::random_access_iterator_test(j, N, array);
|
||||||
|
|
||||||
dummyT*const* const_ptr = ptr;
|
boost::const_nonconst_iterator_test(i, ++j);
|
||||||
|
|
||||||
boost::random_access_iterator_test(boost::make_indirect_iterator<const dummyT>(const_ptr), N, array);
|
|
||||||
|
|
||||||
boost::const_nonconst_iterator_test(i, ++j);
|
|
||||||
|
|
||||||
more_indirect_iterator_tests();
|
|
||||||
}
|
}
|
||||||
|
// Test projection_iterators
|
||||||
// Test projection_iterator_pair_generator
|
|
||||||
{
|
{
|
||||||
typedef std::pair<dummyT,dummyT> Pair;
|
typedef std::pair<dummyT,dummyT> Pair;
|
||||||
Pair pair_array[N];
|
Pair pair_array[N];
|
||||||
for (int k = 0; k < N; ++k)
|
for (int k = 0; k < N; ++k)
|
||||||
pair_array[k].first = array[k];
|
pair_array[k].first = array[k];
|
||||||
|
|
||||||
typedef boost::projection_iterator_pair_generator<select1st_<Pair>,
|
typedef boost::projection_iterators<select1st_<Pair>,
|
||||||
Pair*, const Pair*
|
Pair*, const Pair*,
|
||||||
|
boost::iterator<std::random_access_iterator_tag, Pair>,
|
||||||
|
boost::iterator<std::random_access_iterator_tag, const Pair>
|
||||||
> Projection;
|
> Projection;
|
||||||
|
|
||||||
Projection::iterator i = pair_array;
|
Projection::iterator i = pair_array;
|
||||||
boost::random_access_iterator_test(i, N, 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;
|
Projection::const_iterator j = pair_array;
|
||||||
boost::random_access_iterator_test(j, N, 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);
|
boost::const_nonconst_iterator_test(i, ++j);
|
||||||
}
|
}
|
||||||
// Test reverse_iterator_generator
|
// Test reverse_iterators
|
||||||
{
|
{
|
||||||
dummyT reversed[N];
|
dummyT reversed[N];
|
||||||
std::copy(array, array + N, reversed);
|
std::copy(array, array + N, reversed);
|
||||||
std::reverse(reversed, reversed + N);
|
std::reverse(reversed, reversed + N);
|
||||||
|
|
||||||
typedef boost::reverse_iterator_generator<dummyT*
|
typedef boost::reverse_iterators<dummyT*, const dummyT*,
|
||||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
boost::iterator<std::random_access_iterator_tag,dummyT>,
|
||||||
, dummyT
|
boost::iterator<std::random_access_iterator_tag,const dummyT>
|
||||||
#endif
|
> Reverse;
|
||||||
>::type reverse_iterator;
|
Reverse::iterator i = reversed + N;
|
||||||
|
|
||||||
typedef boost::reverse_iterator_generator<const dummyT*
|
|
||||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
, const dummyT
|
|
||||||
#endif
|
|
||||||
>::type const_reverse_iterator;
|
|
||||||
|
|
||||||
reverse_iterator i = reversed + N;
|
|
||||||
boost::random_access_iterator_test(i, N, array);
|
boost::random_access_iterator_test(i, N, array);
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
Reverse::const_iterator j = reversed + N;
|
||||||
boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const_reverse_iterator j = reversed + N;
|
|
||||||
boost::random_access_iterator_test(j, N, array);
|
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);
|
boost::const_nonconst_iterator_test(i, ++j);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test reverse_iterator_generator again, with traits fully deducible on most platforms
|
|
||||||
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT)
|
|
||||||
{
|
|
||||||
std::deque<dummyT> reversed_container;
|
|
||||||
std::copy(array, array + N, std::back_inserter(reversed_container));
|
|
||||||
const std::deque<dummyT>::iterator reversed = reversed_container.begin();
|
|
||||||
std::reverse(reversed, reversed + N);
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
reverse_iterator i = reversed + N;
|
|
||||||
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(reversed + N);
|
|
||||||
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);
|
|
||||||
|
|
||||||
#if !defined(__GNUC__) || defined(__SGI_STL_PORT) // GCC deque iterators don't allow all const/non-const comparisons
|
|
||||||
boost::const_nonconst_iterator_test(i, ++j);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Test integer_range's iterators
|
// Test integer_range's iterators
|
||||||
{
|
{
|
||||||
int int_array[] = { 0, 1, 2, 3, 4, 5 };
|
int int_array[] = { 0, 1, 2, 3, 4, 5 };
|
||||||
@@ -353,33 +170,7 @@ main()
|
|||||||
boost::random_access_iterator_test(r.begin(), r.size(), int_array);
|
boost::random_access_iterator_test(r.begin(), r.size(), int_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test filter iterator
|
|
||||||
{
|
|
||||||
typedef boost::filter_iterator_generator<one_or_four, dummyT*,
|
|
||||||
boost::iterator<std::forward_iterator_tag, dummyT, std::ptrdiff_t,
|
|
||||||
dummyT*, dummyT&> > FilterGen;
|
|
||||||
typedef FilterGen::type FilterIter;
|
|
||||||
typedef FilterGen::policies_type FilterPolicies;
|
|
||||||
FilterIter i(array, FilterPolicies(one_or_four(), array + N));
|
|
||||||
boost::forward_iterator_test(i, dummyT(1), dummyT(4));
|
|
||||||
|
|
||||||
typedef boost::iterator<std::forward_iterator_tag, dummyT, std::ptrdiff_t, dummyT*, dummyT&> FilterTraits;
|
|
||||||
boost::forward_iterator_test(boost::make_filter_iterator<FilterTraits>
|
|
||||||
(array, array + N, one_or_four() ), dummyT(1), dummyT(4));
|
|
||||||
|
|
||||||
boost::forward_iterator_test(boost::make_filter_iterator<FilterTraits, one_or_four>
|
|
||||||
(array, array + N), dummyT(1), dummyT(4));
|
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
boost::forward_iterator_test(boost::make_filter_iterator(
|
|
||||||
array, 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
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
std::cout << "test successful " << std::endl;
|
std::cout << "test successful " << std::endl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -98,28 +98,18 @@ classes and pass them in <a href="#1">[1]</a>.
|
|||||||
|
|
||||||
|
|
||||||
<p>The <tt>Policies</tt> class that you pass in will become the heart of
|
<p>The <tt>Policies</tt> class that you pass in will become the heart of
|
||||||
the iterator adaptor, supplying the core iterator operations that will determine how your new adaptor
|
the iterator adaptor. The policy class determines how your new adaptor
|
||||||
class will behave. The core iterator operations are:
|
class will behave. The <tt>Policies</tt> class must implement 3, 4, or
|
||||||
<ul>
|
7 of the core iterator operations depending on whether you wish the
|
||||||
<li><code>dereference</code> - returns an element of the iterator's <code>reference</code> type
|
|
||||||
<li><code>equal</code> - tests the iterator for equality
|
|
||||||
<li><code>increment</code> - increments the iterator
|
|
||||||
<li><code>decrement</code> - decrements bidirectional and random-access iterators
|
|
||||||
<li><code>less</code> - imposes a strict weak ordering relation on random-access iterators
|
|
||||||
<li><code>distance</code> - measures the distance between random-access iterators
|
|
||||||
<li><code>advance</code> - adds an integer offset to random-access iterators
|
|
||||||
</ul>
|
|
||||||
The <tt>Policies</tt> class must implement three, four, or
|
|
||||||
seven of the core iterator operations depending on whether you wish the
|
|
||||||
new iterator adaptor class to be a
|
new iterator adaptor class to be a
|
||||||
<a href="http://www.sgi.com/Technology/STL/ForwardIterator.html">
|
<a href="http://www.sgi.com/Technology/STL/ForwardIterator.html">
|
||||||
ForwardIterator</a>,
|
ForwardIterator</a>,
|
||||||
<a href="http://www.sgi.com/Technology/STL/BidirectionalIterator.html">
|
<a href="http://www.sgi.com/Technology/STL/BidirectionalIterator.html">
|
||||||
BidirectionalIterator</a>, or <a
|
BidirectionalIterator</a>, or <a
|
||||||
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
|
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
|
||||||
RandomAccessIterator</a>. The
|
RandomAccessIterator</a>. Make sure that the
|
||||||
<tt>iterator_category</tt> type of the traits class you pass in
|
<tt>iterator_category</tt> type of the traits class you pass in
|
||||||
must match the category of iterator that you want to create. The default
|
matches the category of iterator that you want to create. The default
|
||||||
policy class, <tt>default_iterator_policies</tt>, implements all 7 of
|
policy class, <tt>default_iterator_policies</tt>, implements all 7 of
|
||||||
the core operations in the usual way. If you wish to create an
|
the core operations in the usual way. If you wish to create an
|
||||||
iterator adaptor that only changes a few of the iterator's behaviors,
|
iterator adaptor that only changes a few of the iterator's behaviors,
|
||||||
@@ -807,7 +797,7 @@ uses the three adaptors.
|
|||||||
|
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->10 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14373" --></p>
|
<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><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
|
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
|
||||||
modify, sell and distribute this document is granted provided this copyright
|
modify, sell and distribute this document is granted provided this copyright
|
||||||
notice appears in all copies. This document is provided "as is"
|
notice appears in all copies. This document is provided "as is"
|
||||||
|
@@ -1,155 +0,0 @@
|
|||||||
// (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
|
|
||||||
// 07 Feb 2001 More comprehensive testing; factored out static tests for
|
|
||||||
// better reuse (David Abrahams)
|
|
||||||
// 21 Jan 2001 Quick fix to my_iterator, which wasn't returning a
|
|
||||||
// reference type from operator* (David Abrahams)
|
|
||||||
// 19 Jan 2001 Initial version with iterator operators (David Abrahams)
|
|
||||||
|
|
||||||
#include <boost/detail/iterator.hpp>
|
|
||||||
#include <boost/type_traits.hpp>
|
|
||||||
#include <boost/operators.hpp>
|
|
||||||
#include <boost/static_assert.hpp>
|
|
||||||
#include <iterator>
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
#include <cassert>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
struct my_iterator
|
|
||||||
: public boost::forward_iterator_helper<my_iterator, const char, long>
|
|
||||||
{
|
|
||||||
my_iterator(const char* p) : m_p(p) {}
|
|
||||||
|
|
||||||
bool operator==(const my_iterator& rhs) const
|
|
||||||
{ return this->m_p == rhs.m_p; }
|
|
||||||
|
|
||||||
my_iterator& operator++() { ++this->m_p; return *this; }
|
|
||||||
const char& operator*() { return *m_p; }
|
|
||||||
private:
|
|
||||||
const char* m_p;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template <class Iterator,
|
|
||||||
class value_type, class difference_type, class pointer, class reference, class category>
|
|
||||||
struct non_portable_tests
|
|
||||||
{
|
|
||||||
// Unfortunately, the VC6 standard library doesn't supply these :(
|
|
||||||
BOOST_STATIC_ASSERT((
|
|
||||||
boost::is_same<
|
|
||||||
typename boost::detail::iterator_traits<Iterator>::pointer,
|
|
||||||
pointer
|
|
||||||
>::value));
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT((
|
|
||||||
boost::is_same<
|
|
||||||
typename boost::detail::iterator_traits<Iterator>::reference,
|
|
||||||
reference
|
|
||||||
>::value));
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Iterator,
|
|
||||||
class value_type, class difference_type, class pointer, class reference, class category>
|
|
||||||
struct portable_tests
|
|
||||||
{
|
|
||||||
BOOST_STATIC_ASSERT((
|
|
||||||
boost::is_same<
|
|
||||||
typename boost::detail::iterator_traits<Iterator>::difference_type,
|
|
||||||
difference_type
|
|
||||||
>::value));
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT((
|
|
||||||
boost::is_same<
|
|
||||||
typename boost::detail::iterator_traits<Iterator>::iterator_category,
|
|
||||||
category
|
|
||||||
>::value));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Test iterator_traits
|
|
||||||
template <class Iterator,
|
|
||||||
class value_type, class difference_type, class pointer, class reference, class category>
|
|
||||||
struct input_iterator_test
|
|
||||||
: portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
|
|
||||||
{
|
|
||||||
BOOST_STATIC_ASSERT((
|
|
||||||
boost::is_same<
|
|
||||||
typename boost::detail::iterator_traits<Iterator>::value_type,
|
|
||||||
value_type
|
|
||||||
>::value));
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Iterator,
|
|
||||||
class value_type, class difference_type, class pointer, class reference, class category>
|
|
||||||
struct non_pointer_test
|
|
||||||
: input_iterator_test<Iterator,value_type,difference_type,pointer,reference,category>
|
|
||||||
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT)
|
|
||||||
, non_portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Iterator,
|
|
||||||
class value_type, class difference_type, class pointer, class reference, class category>
|
|
||||||
struct maybe_pointer_test
|
|
||||||
: portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
, non_portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
input_iterator_test<std::istream_iterator<int>, int, std::ptrdiff_t, int*, int&, std::input_iterator_tag>
|
|
||||||
istream_iterator_test;
|
|
||||||
|
|
||||||
non_pointer_test<std::ostream_iterator<int>,
|
|
||||||
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT)
|
|
||||||
void,
|
|
||||||
#else // the VC6 standard lib gives ostream_iterator an incorrect value_type
|
|
||||||
int,
|
|
||||||
#endif
|
|
||||||
void, void, void, std::output_iterator_tag>
|
|
||||||
ostream_iterator_test;
|
|
||||||
|
|
||||||
#ifdef __KCC
|
|
||||||
typedef long std_list_diff_type;
|
|
||||||
#else
|
|
||||||
typedef std::ptrdiff_t std_list_diff_type;
|
|
||||||
#endif
|
|
||||||
non_pointer_test<std::list<int>::iterator, int, std_list_diff_type, int*, int&, std::bidirectional_iterator_tag>
|
|
||||||
list_iterator_test;
|
|
||||||
|
|
||||||
maybe_pointer_test<std::vector<int>::iterator, int, std::ptrdiff_t, int*, int&, std::random_access_iterator_tag>
|
|
||||||
vector_iterator_test;
|
|
||||||
|
|
||||||
maybe_pointer_test<int*, int, std::ptrdiff_t, int*, int&, std::random_access_iterator_tag>
|
|
||||||
int_pointer_test;
|
|
||||||
|
|
||||||
non_pointer_test<my_iterator, const char, long, const char*, const char&, std::forward_iterator_tag>
|
|
||||||
my_iterator_test;
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
char chars[100];
|
|
||||||
int ints[100];
|
|
||||||
|
|
||||||
for (std::ptrdiff_t length = 3; length < 100; length += length / 3)
|
|
||||||
{
|
|
||||||
std::list<int> l(length);
|
|
||||||
assert(boost::detail::distance(l.begin(), l.end()) == length);
|
|
||||||
|
|
||||||
std::vector<int> v(length);
|
|
||||||
assert(boost::detail::distance(v.begin(), v.end()) == length);
|
|
||||||
|
|
||||||
assert(boost::detail::distance(&ints[0], ints + length) == length);
|
|
||||||
assert(boost::detail::distance(my_iterator(chars), my_iterator(chars + length)) == length);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
@@ -1,385 +0,0 @@
|
|||||||
// (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
|
|
||||||
// 23 Jan 2001 Added test for wchar_t (David Abrahams)
|
|
||||||
// 23 Jan 2001 Now statically selecting a test for signed numbers to avoid
|
|
||||||
// warnings with fancy compilers. Added commentary and
|
|
||||||
// additional dumping of traits data for tested types (David
|
|
||||||
// Abrahams).
|
|
||||||
// 21 Jan 2001 Initial version (David Abrahams)
|
|
||||||
|
|
||||||
#include <boost/detail/numeric_traits.hpp>
|
|
||||||
#include <cassert>
|
|
||||||
#include <boost/type_traits.hpp>
|
|
||||||
#include <boost/static_assert.hpp>
|
|
||||||
#include <boost/cstdint.hpp>
|
|
||||||
#include <boost/utility.hpp>
|
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
#include <climits>
|
|
||||||
#include <typeinfo>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#ifndef BOOST_NO_LIMITS
|
|
||||||
# include <limits>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// A macro for declaring class compile-time constants.
|
|
||||||
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
|
|
||||||
# define DECLARE_CLASS_CONST(type, init) static const type init
|
|
||||||
#else
|
|
||||||
# define DECLARE_CLASS_CONST(type, init) enum { init }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// =================================================================================
|
|
||||||
// template class complement_traits<Number> --
|
|
||||||
//
|
|
||||||
// statically computes the max and min for 1s and 2s-complement binary
|
|
||||||
// numbers. This helps on platforms without <limits> support. It also shows
|
|
||||||
// an example of a recursive template that works with MSVC!
|
|
||||||
//
|
|
||||||
|
|
||||||
template <unsigned size> struct complement; // forward
|
|
||||||
|
|
||||||
// The template complement, below, does all the real work, using "poor man's
|
|
||||||
// partial specialization". We need complement_traits_aux<> so that MSVC doesn't
|
|
||||||
// complain about undefined min/max as we're trying to recursively define them.
|
|
||||||
template <class Number, unsigned size>
|
|
||||||
struct complement_traits_aux
|
|
||||||
{
|
|
||||||
DECLARE_CLASS_CONST(Number, max = complement<size>::template traits<Number>::max);
|
|
||||||
DECLARE_CLASS_CONST(Number, min = complement<size>::template traits<Number>::min);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <unsigned size>
|
|
||||||
struct complement
|
|
||||||
{
|
|
||||||
template <class Number>
|
|
||||||
struct traits
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
// indirection through complement_traits_aux neccessary to keep MSVC happy
|
|
||||||
typedef complement_traits_aux<Number, size - 1> prev;
|
|
||||||
public:
|
|
||||||
DECLARE_CLASS_CONST(Number, max =
|
|
||||||
Number(Number(prev::max) << CHAR_BIT)
|
|
||||||
+ Number(UCHAR_MAX));
|
|
||||||
|
|
||||||
DECLARE_CLASS_CONST(Number, min = Number(Number(prev::min) << CHAR_BIT));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Template class complement_base<> -- defines values for min and max for
|
|
||||||
// complement<1>, at the deepest level of recursion. Uses "poor man's partial
|
|
||||||
// specialization" again.
|
|
||||||
template <bool is_signed> struct complement_base;
|
|
||||||
|
|
||||||
template <> struct complement_base<false>
|
|
||||||
{
|
|
||||||
template <class Number>
|
|
||||||
struct values
|
|
||||||
{
|
|
||||||
DECLARE_CLASS_CONST(Number, min = 0);
|
|
||||||
DECLARE_CLASS_CONST(Number, max = UCHAR_MAX);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <> struct complement_base<true>
|
|
||||||
{
|
|
||||||
template <class Number>
|
|
||||||
struct values
|
|
||||||
{
|
|
||||||
DECLARE_CLASS_CONST(Number, min = SCHAR_MIN);
|
|
||||||
DECLARE_CLASS_CONST(Number, max = SCHAR_MAX);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Base specialization of complement, puts an end to the recursion.
|
|
||||||
template <>
|
|
||||||
struct complement<1>
|
|
||||||
{
|
|
||||||
template <class Number>
|
|
||||||
struct traits
|
|
||||||
{
|
|
||||||
DECLARE_CLASS_CONST(bool, is_signed = boost::detail::is_signed<Number>::value);
|
|
||||||
DECLARE_CLASS_CONST(Number, min =
|
|
||||||
complement_base<is_signed>::template values<Number>::min);
|
|
||||||
DECLARE_CLASS_CONST(Number, max =
|
|
||||||
complement_base<is_signed>::template values<Number>::max);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Now here's the "pretty" template you're intended to actually use.
|
|
||||||
// complement_traits<Number>::min, complement_traits<Number>::max are the
|
|
||||||
// minimum and maximum values of Number if Number is a built-in integer type.
|
|
||||||
template <class Number>
|
|
||||||
struct complement_traits
|
|
||||||
{
|
|
||||||
DECLARE_CLASS_CONST(Number, max = (complement_traits_aux<Number, sizeof(Number)>::max));
|
|
||||||
DECLARE_CLASS_CONST(Number, min = (complement_traits_aux<Number, sizeof(Number)>::min));
|
|
||||||
};
|
|
||||||
|
|
||||||
// =================================================================================
|
|
||||||
|
|
||||||
// Support for streaming various numeric types in exactly the format I want. I
|
|
||||||
// needed this in addition to all the assertions so that I could see exactly
|
|
||||||
// what was going on.
|
|
||||||
//
|
|
||||||
// Numbers go through a 2-stage conversion process (by default, though, no real
|
|
||||||
// conversion).
|
|
||||||
//
|
|
||||||
template <class T> struct stream_as {
|
|
||||||
typedef T t1;
|
|
||||||
typedef T t2;
|
|
||||||
};
|
|
||||||
|
|
||||||
// char types first get converted to unsigned char, then to unsigned.
|
|
||||||
template <> struct stream_as<char> {
|
|
||||||
typedef unsigned char t1;
|
|
||||||
typedef unsigned t2;
|
|
||||||
};
|
|
||||||
template <> struct stream_as<unsigned char> {
|
|
||||||
typedef unsigned char t1; typedef unsigned t2;
|
|
||||||
};
|
|
||||||
template <> struct stream_as<signed char> {
|
|
||||||
typedef unsigned char t1; typedef unsigned t2;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(BOOST_MSVC) // No intmax streaming built-in
|
|
||||||
|
|
||||||
// On this platform, __int64 and __uint64 get streamed as strings
|
|
||||||
template <> struct stream_as<boost::uintmax_t> {
|
|
||||||
typedef std::string t1;
|
|
||||||
typedef std::string t2;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <> struct stream_as<boost::intmax_t> {
|
|
||||||
typedef std::string t1;
|
|
||||||
typedef std::string t2;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Standard promotion process for streaming
|
|
||||||
template <class T> struct promote
|
|
||||||
{
|
|
||||||
static typename stream_as<T>::t1 from(T x) {
|
|
||||||
typedef typename stream_as<T>::t1 t1;
|
|
||||||
return t1(x);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(BOOST_MSVC) // No intmax streaming built-in
|
|
||||||
|
|
||||||
// On this platform, stream them as long/unsigned long if they fit.
|
|
||||||
// Otherwise, write a string.
|
|
||||||
template <> struct promote<boost::uintmax_t> {
|
|
||||||
std::string static from(const boost::uintmax_t x) {
|
|
||||||
if (x > ULONG_MAX)
|
|
||||||
return std::string("large unsigned value");
|
|
||||||
else
|
|
||||||
return boost::lexical_cast<std::string>((unsigned long)x);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template <> struct promote<boost::intmax_t> {
|
|
||||||
std::string static from(const boost::intmax_t x) {
|
|
||||||
if (x > boost::intmax_t(ULONG_MAX))
|
|
||||||
return std::string("large positive signed value");
|
|
||||||
else if (x >= 0)
|
|
||||||
return boost::lexical_cast<std::string>((unsigned long)x);
|
|
||||||
|
|
||||||
if (x < boost::intmax_t(LONG_MIN))
|
|
||||||
return std::string("large negative signed value");
|
|
||||||
else
|
|
||||||
return boost::lexical_cast<std::string>((long)x);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// This is the function which converts types to the form I want to stream them in.
|
|
||||||
template <class T>
|
|
||||||
typename stream_as<T>::t2 stream_number(T x)
|
|
||||||
{
|
|
||||||
return promote<T>::from(x);
|
|
||||||
}
|
|
||||||
// =================================================================================
|
|
||||||
|
|
||||||
//
|
|
||||||
// Tests for built-in signed and unsigned types
|
|
||||||
//
|
|
||||||
|
|
||||||
// Tag types for selecting tests
|
|
||||||
struct unsigned_tag {};
|
|
||||||
struct signed_tag {};
|
|
||||||
|
|
||||||
// Tests for unsigned numbers. The extra default Number parameter works around
|
|
||||||
// an MSVC bug.
|
|
||||||
template <class Number>
|
|
||||||
void test_aux(unsigned_tag, Number* = 0)
|
|
||||||
{
|
|
||||||
typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
|
|
||||||
BOOST_STATIC_ASSERT(!boost::detail::is_signed<Number>::value);
|
|
||||||
BOOST_STATIC_ASSERT(
|
|
||||||
(sizeof(Number) < sizeof(boost::intmax_t))
|
|
||||||
| (boost::is_same<difference_type, boost::intmax_t>::value));
|
|
||||||
|
|
||||||
// Force casting to Number here to work around the fact that it's an enum on MSVC
|
|
||||||
BOOST_STATIC_ASSERT(Number(complement_traits<Number>::max) > Number(0));
|
|
||||||
BOOST_STATIC_ASSERT(Number(complement_traits<Number>::min) == Number(0));
|
|
||||||
|
|
||||||
const Number max = complement_traits<Number>::max;
|
|
||||||
const Number min = complement_traits<Number>::min;
|
|
||||||
|
|
||||||
const Number test_max = (sizeof(Number) < sizeof(boost::intmax_t))
|
|
||||||
? max
|
|
||||||
: max / 2 - 1;
|
|
||||||
|
|
||||||
std::cout << std::hex << "(unsigned) min = " << stream_number(min) << ", max = "
|
|
||||||
<< stream_number(max) << "..." << std::flush;
|
|
||||||
std::cout << "difference_type = " << typeid(difference_type).name() << "..."
|
|
||||||
<< std::flush;
|
|
||||||
|
|
||||||
difference_type d1 = boost::detail::numeric_distance(Number(0), test_max);
|
|
||||||
difference_type d2 = boost::detail::numeric_distance(test_max, Number(0));
|
|
||||||
|
|
||||||
std::cout << "0->" << stream_number(test_max) << "==" << std::dec << stream_number(d1) << "; "
|
|
||||||
<< std::hex << stream_number(test_max) << "->0==" << std::dec << stream_number(d2) << "..." << std::flush;
|
|
||||||
|
|
||||||
assert(d1 == difference_type(test_max));
|
|
||||||
assert(d2 == -difference_type(test_max));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests for signed numbers. The extra default Number parameter works around an
|
|
||||||
// MSVC bug.
|
|
||||||
struct out_of_range_tag {};
|
|
||||||
struct in_range_tag {};
|
|
||||||
|
|
||||||
// This test morsel gets executed for numbers whose difference will always be
|
|
||||||
// representable in intmax_t
|
|
||||||
template <class Number>
|
|
||||||
void signed_test(in_range_tag, Number* = 0)
|
|
||||||
{
|
|
||||||
BOOST_STATIC_ASSERT(boost::detail::is_signed<Number>::value);
|
|
||||||
typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
|
|
||||||
const Number max = complement_traits<Number>::max;
|
|
||||||
const Number min = complement_traits<Number>::min;
|
|
||||||
|
|
||||||
difference_type d1 = boost::detail::numeric_distance(min, max);
|
|
||||||
difference_type d2 = boost::detail::numeric_distance(max, min);
|
|
||||||
|
|
||||||
std::cout << stream_number(min) << "->" << stream_number(max) << "==";
|
|
||||||
std::cout << std::dec << stream_number(d1) << "; ";
|
|
||||||
std::cout << std::hex << stream_number(max) << "->" << stream_number(min)
|
|
||||||
<< "==" << std::dec << stream_number(d2) << "..." << std::flush;
|
|
||||||
assert(d1 == difference_type(max) - difference_type(min));
|
|
||||||
assert(d2 == difference_type(min) - difference_type(max));
|
|
||||||
}
|
|
||||||
|
|
||||||
// This test morsel gets executed for numbers whose difference may exceed the
|
|
||||||
// capacity of intmax_t.
|
|
||||||
template <class Number>
|
|
||||||
void signed_test(out_of_range_tag, Number* = 0)
|
|
||||||
{
|
|
||||||
BOOST_STATIC_ASSERT(boost::detail::is_signed<Number>::value);
|
|
||||||
typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
|
|
||||||
const Number max = complement_traits<Number>::max;
|
|
||||||
const Number min = complement_traits<Number>::min;
|
|
||||||
|
|
||||||
difference_type min_distance = complement_traits<difference_type>::min;
|
|
||||||
difference_type max_distance = complement_traits<difference_type>::max;
|
|
||||||
|
|
||||||
const Number n1 = Number(min + max_distance);
|
|
||||||
const Number n2 = Number(max + min_distance);
|
|
||||||
difference_type d1 = boost::detail::numeric_distance(min, n1);
|
|
||||||
difference_type d2 = boost::detail::numeric_distance(max, n2);
|
|
||||||
|
|
||||||
std::cout << stream_number(min) << "->" << stream_number(n1) << "==";
|
|
||||||
std::cout << std::dec << stream_number(d1) << "; ";
|
|
||||||
std::cout << std::hex << stream_number(max) << "->" << stream_number(n2)
|
|
||||||
<< "==" << std::dec << stream_number(d2) << "..." << std::flush;
|
|
||||||
assert(d1 == max_distance);
|
|
||||||
assert(d2 == min_distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Number>
|
|
||||||
void test_aux(signed_tag, Number* = 0)
|
|
||||||
{
|
|
||||||
typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
|
|
||||||
BOOST_STATIC_ASSERT(boost::detail::is_signed<Number>::value);
|
|
||||||
BOOST_STATIC_ASSERT(
|
|
||||||
(sizeof(Number) < sizeof(boost::intmax_t))
|
|
||||||
| (boost::is_same<difference_type, Number>::value));
|
|
||||||
|
|
||||||
// Force casting to Number here to work around the fact that it's an enum on MSVC
|
|
||||||
BOOST_STATIC_ASSERT(Number(complement_traits<Number>::max) > Number(0));
|
|
||||||
BOOST_STATIC_ASSERT(Number(complement_traits<Number>::min) < Number(0));
|
|
||||||
|
|
||||||
const Number max = complement_traits<Number>::max;
|
|
||||||
const Number min = complement_traits<Number>::min;
|
|
||||||
|
|
||||||
std::cout << std::hex << "min = " << stream_number(min) << ", max = "
|
|
||||||
<< stream_number(max) << "..." << std::flush;
|
|
||||||
std::cout << "difference_type = " << typeid(difference_type).name() << "..."
|
|
||||||
<< std::flush;
|
|
||||||
|
|
||||||
typedef typename boost::detail::if_true<
|
|
||||||
(sizeof(Number) < sizeof(boost::intmax_t))>
|
|
||||||
::template then<
|
|
||||||
in_range_tag,
|
|
||||||
out_of_range_tag
|
|
||||||
>::type
|
|
||||||
range_tag;
|
|
||||||
signed_test<Number>(range_tag());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Test for all numbers. The extra default Number parameter works around an MSVC
|
|
||||||
// bug.
|
|
||||||
template <class Number>
|
|
||||||
void test(Number* = 0)
|
|
||||||
{
|
|
||||||
std::cout << "testing " << typeid(Number).name() << ":\n"
|
|
||||||
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
|
|
||||||
<< "is_signed: " << (std::numeric_limits<Number>::is_signed ? "true\n" : "false\n")
|
|
||||||
<< "is_bounded: " << (std::numeric_limits<Number>::is_bounded ? "true\n" : "false\n")
|
|
||||||
<< "digits: " << std::numeric_limits<Number>::digits << "\n"
|
|
||||||
#endif
|
|
||||||
<< "..." << std::flush;
|
|
||||||
typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
|
|
||||||
BOOST_STATIC_ASSERT(boost::detail::is_signed<difference_type>::value);
|
|
||||||
|
|
||||||
typedef typename boost::detail::if_true<
|
|
||||||
boost::detail::is_signed<Number>::value
|
|
||||||
>::template then<signed_tag, unsigned_tag>::type signedness;
|
|
||||||
|
|
||||||
test_aux<Number>(signedness());
|
|
||||||
std::cout << "passed" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
test<char>();
|
|
||||||
test<unsigned char>();
|
|
||||||
test<signed char>();
|
|
||||||
test<wchar_t>();
|
|
||||||
test<short>();
|
|
||||||
test<unsigned short>();
|
|
||||||
test<int>();
|
|
||||||
test<unsigned int>();
|
|
||||||
test<long>();
|
|
||||||
test<unsigned long>();
|
|
||||||
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
|
|
||||||
test<long long>();
|
|
||||||
test<unsigned long long>();
|
|
||||||
#elif defined(BOOST_MSVC)
|
|
||||||
// The problem of not having compile-time static class constants other than
|
|
||||||
// enums prevents this from working, since values get truncated.
|
|
||||||
// test<boost::uintmax_t>();
|
|
||||||
// test<boost::intmax_t>();
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
@@ -585,7 +585,7 @@ complicated than the old one, we think it's worth it to make the library more
|
|||||||
useful in real world. Alexy Gurtovoy contributed the code which supports the new
|
useful in real world. Alexy Gurtovoy contributed the code which supports the new
|
||||||
usage idiom while allowing the library remain backward-compatible.</p>
|
usage idiom while allowing the library remain backward-compatible.</p>
|
||||||
<hr>
|
<hr>
|
||||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->28 Sep 2000<!--webbot bot="Timestamp" endspan i-checksum="14938" --></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 David Abrahams and Beman Dawes 1999-2000. Permission to copy,
|
<p><EFBFBD> Copyright David Abrahams and Beman Dawes 1999-2000. Permission to copy,
|
||||||
use, modify, sell and distribute this document is granted provided this
|
use, modify, sell and distribute this document is granted provided this
|
||||||
copyright notice appears in all copies. This document is provided "as
|
copyright notice appears in all copies. This document is provided "as
|
||||||
|
@@ -7,24 +7,14 @@
|
|||||||
// standalone test program for <boost/type_traits.hpp>
|
// standalone test program for <boost/type_traits.hpp>
|
||||||
|
|
||||||
/* Release notes:
|
/* Release notes:
|
||||||
31 Jan 2001:
|
|
||||||
Added a test for is_array using a const array and a test for
|
|
||||||
is_convertible with a user-defined implicit conversion. Changed
|
|
||||||
signature of main() so that this program will link under
|
|
||||||
MSVC. (Jeremy Siek)
|
|
||||||
20 Jan 2001:
|
|
||||||
Suppress an expected warning for MSVC
|
|
||||||
Added a test to prove that we can use void with is_same<>
|
|
||||||
Removed "press any key to exit" as it interferes with testing in large
|
|
||||||
batches.
|
|
||||||
(David Abahams)
|
|
||||||
31st July 2000:
|
31st July 2000:
|
||||||
Added extra tests for is_empty, is_convertible, alignment_of.
|
Added extra tests for is_empty, is_convertible, alignment_of.
|
||||||
23rd July 2000:
|
23rd July 2000:
|
||||||
Removed all call_traits tests to call_traits_test.cpp
|
Removed all call_traits tests to call_traits_test.cpp
|
||||||
Removed all compressed_pair tests to compressed_pair_tests.cpp
|
Removed all compressed_pair tests to compressed_pair_tests.cpp
|
||||||
Improved tests macros
|
Improved tests macros
|
||||||
Tidied up specialistions of type_types classes for test cases. */
|
Tidied up specialistions of type_types classes for test cases.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
@@ -150,7 +140,7 @@ template <> struct is_POD<empty_POD_union_UDT>
|
|||||||
|
|
||||||
class Base { };
|
class Base { };
|
||||||
|
|
||||||
class Derived : public Base { };
|
class Deriverd : public Base { };
|
||||||
|
|
||||||
class NonDerived { };
|
class NonDerived { };
|
||||||
|
|
||||||
@@ -192,32 +182,19 @@ struct non_empty : boost::noncopyable
|
|||||||
int i;
|
int i;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct implicitly_convertible_to_int {
|
|
||||||
operator int() { return 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Steve: All comments that I (Steve Cleary) have added below are prefixed with
|
// Steve: All comments that I (Steve Cleary) have added below are prefixed with
|
||||||
// "Steve:" The failures that BCB4 has on the tests are due to Borland's
|
// "Steve:" The failures that BCB4 has on the tests are due to Borland's
|
||||||
// not considering cv-qual's as a part of the type -- they are considered
|
// not considering cv-qual's as a part of the type -- they are considered
|
||||||
// compiler hints only. These failures should be fixed before long.
|
// compiler hints only. These failures should be fixed before long.
|
||||||
|
|
||||||
int main(int, char*[])
|
int main()
|
||||||
{
|
{
|
||||||
std::cout << "Checking type operations..." << std::endl << std::endl;
|
std::cout << "Checking type operations..." << std::endl << std::endl;
|
||||||
|
|
||||||
// cv-qualifiers applied to reference types should have no effect
|
// cv-qualifiers applied to reference types should have no effect
|
||||||
// declare these here for later use with is_reference and remove_reference:
|
// declare these here for later use with is_reference and remove_reference:
|
||||||
typedef int& r_type;
|
typedef int& r_type;
|
||||||
#ifdef BOOST_MSVC
|
|
||||||
# pragma warning(push)
|
|
||||||
# pragma warning(disable:4181) // qualifier applied to reference type ignored
|
|
||||||
#endif
|
|
||||||
typedef const r_type cr_type;
|
typedef const r_type cr_type;
|
||||||
#ifdef BOOST_MSVC
|
|
||||||
# pragma warning(pop)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
type_test(int, remove_reference<int>::type)
|
type_test(int, remove_reference<int>::type)
|
||||||
type_test(const int, remove_reference<const int>::type)
|
type_test(const int, remove_reference<const int>::type)
|
||||||
@@ -255,9 +232,6 @@ int main(int, char*[])
|
|||||||
|
|
||||||
std::cout << std::endl << "Checking type properties..." << std::endl << std::endl;
|
std::cout << std::endl << "Checking type properties..." << std::endl << std::endl;
|
||||||
|
|
||||||
value_test(true, (is_same<void, void>::value))
|
|
||||||
value_test(false, (is_same<int, void>::value))
|
|
||||||
value_test(false, (is_same<void, int>::value))
|
|
||||||
value_test(true, (is_same<int, int>::value))
|
value_test(true, (is_same<int, int>::value))
|
||||||
value_test(false, (is_same<int, const int>::value))
|
value_test(false, (is_same<int, const int>::value))
|
||||||
value_test(false, (is_same<int, int&>::value))
|
value_test(false, (is_same<int, int&>::value))
|
||||||
@@ -417,7 +391,6 @@ int main(int, char*[])
|
|||||||
value_test(true, is_array<int[2][3]>::value)
|
value_test(true, is_array<int[2][3]>::value)
|
||||||
value_test(true, is_array<UDT[2]>::value)
|
value_test(true, is_array<UDT[2]>::value)
|
||||||
value_test(false, is_array<int(&)[2]>::value)
|
value_test(false, is_array<int(&)[2]>::value)
|
||||||
value_test(true, is_array<const int[2]>::value)
|
|
||||||
|
|
||||||
typedef void(*f1)();
|
typedef void(*f1)();
|
||||||
typedef int(*f2)(int);
|
typedef int(*f2)(int);
|
||||||
@@ -610,13 +583,11 @@ int main(int, char*[])
|
|||||||
value_test(false, is_POD<empty_UDT>::value)
|
value_test(false, is_POD<empty_UDT>::value)
|
||||||
value_test(true, is_POD<enum_UDT>::value)
|
value_test(true, is_POD<enum_UDT>::value)
|
||||||
|
|
||||||
value_test(true, (boost::is_convertible<implicitly_convertible_to_int,
|
value_test(true, (boost::is_convertible<Deriverd,Base>::value));
|
||||||
int>::value));
|
value_test(true, (boost::is_convertible<Deriverd,Deriverd>::value));
|
||||||
value_test(true, (boost::is_convertible<Derived,Base>::value));
|
|
||||||
value_test(true, (boost::is_convertible<Derived,Derived>::value));
|
|
||||||
value_test(true, (boost::is_convertible<Base,Base>::value));
|
value_test(true, (boost::is_convertible<Base,Base>::value));
|
||||||
value_test(false, (boost::is_convertible<Base,Derived>::value));
|
value_test(false, (boost::is_convertible<Base,Deriverd>::value));
|
||||||
value_test(true, (boost::is_convertible<Derived,Derived>::value));
|
value_test(true, (boost::is_convertible<Deriverd,Deriverd>::value));
|
||||||
value_test(false, (boost::is_convertible<NonDerived,Base>::value));
|
value_test(false, (boost::is_convertible<NonDerived,Base>::value));
|
||||||
value_test(false, (boost::is_convertible<boost::noncopyable, int>::value));
|
value_test(false, (boost::is_convertible<boost::noncopyable, int>::value));
|
||||||
value_test(true, (boost::is_convertible<float,int>::value));
|
value_test(true, (boost::is_convertible<float,int>::value));
|
||||||
@@ -626,14 +597,14 @@ int main(int, char*[])
|
|||||||
value_test(true, (boost::is_convertible<void,void>::value));
|
value_test(true, (boost::is_convertible<void,void>::value));
|
||||||
#endif
|
#endif
|
||||||
value_test(true, (boost::is_convertible<enum1, int>::value));
|
value_test(true, (boost::is_convertible<enum1, int>::value));
|
||||||
value_test(true, (boost::is_convertible<Derived*, Base*>::value));
|
value_test(true, (boost::is_convertible<Deriverd*, Base*>::value));
|
||||||
value_test(false, (boost::is_convertible<Base*, Derived*>::value));
|
value_test(false, (boost::is_convertible<Base*, Deriverd*>::value));
|
||||||
value_test(true, (boost::is_convertible<Derived&, Base&>::value));
|
value_test(true, (boost::is_convertible<Deriverd&, Base&>::value));
|
||||||
value_test(false, (boost::is_convertible<Base&, Derived&>::value));
|
value_test(false, (boost::is_convertible<Base&, Deriverd&>::value));
|
||||||
value_test(true, (boost::is_convertible<const Derived*, const Base*>::value));
|
value_test(true, (boost::is_convertible<const Deriverd*, const Base*>::value));
|
||||||
value_test(false, (boost::is_convertible<const Base*, const Derived*>::value));
|
value_test(false, (boost::is_convertible<const Base*, const Deriverd*>::value));
|
||||||
value_test(true, (boost::is_convertible<const Derived&, const Base&>::value));
|
value_test(true, (boost::is_convertible<const Deriverd&, const Base&>::value));
|
||||||
value_test(false, (boost::is_convertible<const Base&, const Derived&>::value));
|
value_test(false, (boost::is_convertible<const Base&, const Deriverd&>::value));
|
||||||
|
|
||||||
value_test(false, (boost::is_convertible<const int *, int*>::value));
|
value_test(false, (boost::is_convertible<const int *, int*>::value));
|
||||||
value_test(false, (boost::is_convertible<const int&, int&>::value));
|
value_test(false, (boost::is_convertible<const int&, int&>::value));
|
||||||
@@ -663,7 +634,8 @@ int main(int, char*[])
|
|||||||
align_test(VB);
|
align_test(VB);
|
||||||
align_test(VD);
|
align_test(VD);
|
||||||
|
|
||||||
std::cout << std::endl << test_count << " tests completed (" << failures << " failures)";
|
std::cout << std::endl << test_count << " tests completed (" << failures << " failures)... press any key to exit";
|
||||||
|
std::cin.get();
|
||||||
return failures;
|
return failures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
// boost::compressed_pair test program
|
// boost::compressed_pair test program
|
||||||
|
|
||||||
// (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and
|
// (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and
|
||||||
// distribute this software is granted provided this copyright notice appears
|
// distribute this software is granted provided this copyright notice appears
|
||||||
// in all copies. This software is provided "as is" without express or implied
|
// 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.
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
|
||||||
// common test code for type_traits_test.cpp/call_traits_test.cpp/compressed_pair_test.cpp
|
// common test code for type_traits_test.cpp/call_traits_test.cpp/compressed_pair_test.cpp
|
||||||
|
|
||||||
@@ -11,10 +11,6 @@
|
|||||||
#ifndef BOOST_TYPE_TRAITS_TEST_HPP
|
#ifndef BOOST_TYPE_TRAITS_TEST_HPP
|
||||||
#define BOOST_TYPE_TRAITS_TEST_HPP
|
#define BOOST_TYPE_TRAITS_TEST_HPP
|
||||||
|
|
||||||
// Variable declarations must come before test_align due to two-phase lookup
|
|
||||||
unsigned failures = 0;
|
|
||||||
unsigned test_count = 0;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// this one is here just to suppress warnings:
|
// this one is here just to suppress warnings:
|
||||||
//
|
//
|
||||||
@@ -98,6 +94,8 @@ struct test_align<T&>
|
|||||||
|
|
||||||
//
|
//
|
||||||
// define tests here
|
// define tests here
|
||||||
|
unsigned failures = 0;
|
||||||
|
unsigned test_count = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// turn off some warnings:
|
// turn off some warnings:
|
||||||
|
Reference in New Issue
Block a user