mirror of
https://github.com/boostorg/utility.git
synced 2025-10-05 13:30:55 +02:00
Compare commits
44 Commits
boost-1.19
...
boost-1.20
Author | SHA1 | Date | |
---|---|---|---|
|
f0214615b5 | ||
|
228cdcf05e | ||
|
42598e352c | ||
|
36a9e4d1da | ||
|
456dfd0dea | ||
|
155457e2b5 | ||
|
b5c91485bf | ||
|
c959cf7870 | ||
|
5878c88636 | ||
|
ddcef2fb19 | ||
|
493d124c07 | ||
|
f42060c616 | ||
|
834facc932 | ||
|
f82d0b76ee | ||
|
c25d225275 | ||
|
c503a274b5 | ||
|
087069d215 | ||
|
826a6dd114 | ||
|
f31483838d | ||
|
d8a9b633d9 | ||
|
c060e4466a | ||
|
a9951376f4 | ||
|
bda0c8f5e3 | ||
|
71902f23a2 | ||
|
dfd6c85569 | ||
|
0e41b2cc1a | ||
|
e5c81d0702 | ||
|
6caf7d4d5a | ||
|
98e87c8afb | ||
|
d9e0f80d50 | ||
|
6396fdb5ff | ||
|
2470b53373 | ||
|
16334e92ca | ||
|
c22d98a8ec | ||
|
28617afbb9 | ||
|
0c3bc42bec | ||
|
e3d9745df1 | ||
|
b8471c1015 | ||
|
045b09c9ef | ||
|
4ac07b97d3 | ||
|
34c847c17f | ||
|
f694e557e1 | ||
|
6a0c3e92a0 | ||
|
cba48df8e3 |
148
cast.htm
148
cast.htm
@@ -1,148 +0,0 @@
|
||||
<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
153
cast_test.cpp
@@ -1,153 +0,0 @@
|
||||
// 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,6 +78,9 @@ int main()
|
||||
compressed_pair<non_empty1, non_empty2> cp1d(non_empty2(9));
|
||||
assert(cp1d.second() == non_empty2(9));
|
||||
assert(cp1d.first() == non_empty1());
|
||||
|
||||
compressed_pair<int, double> cp1e(cp1);
|
||||
|
||||
compressed_pair<empty_UDT, int> cp2(2);
|
||||
assert(cp2.second() == 2);
|
||||
compressed_pair<int, empty_UDT> cp3(1);
|
||||
|
189
counting_iterator_test.cpp
Normal file
189
counting_iterator_test.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
// (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;
|
||||
}
|
367
half_open_range_test.cpp
Normal file
367
half_open_range_test.cpp
Normal file
@@ -0,0 +1,367 @@
|
||||
// (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,6 +8,8 @@
|
||||
// see libs/utility/compressed_pair.hpp
|
||||
//
|
||||
/* Release notes:
|
||||
20 Jan 2001:
|
||||
Fixed obvious bugs (David Abrahams)
|
||||
07 Oct 2000:
|
||||
Added better single argument constructor support.
|
||||
03 Oct 2000:
|
||||
@@ -42,10 +44,14 @@ namespace boost
|
||||
// have one template single-argument constructor
|
||||
// in place of two specific constructors:
|
||||
//
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair;
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class A, class T1, class T2>
|
||||
struct best_convertion_traits
|
||||
struct best_conversion_traits
|
||||
{
|
||||
typedef char one;
|
||||
typedef char (&two)[2];
|
||||
@@ -102,8 +108,20 @@ public:
|
||||
template <class A>
|
||||
explicit compressed_pair_0(const A& val)
|
||||
{
|
||||
init_one<best_convertion_traits<A, T1, T2>::value>::init(val, &_first, &_second);
|
||||
init_one<best_conversion_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_const_reference first() const { return _first; }
|
||||
@@ -137,12 +155,27 @@ public:
|
||||
|
||||
compressed_pair_1() : T2(), _first() {}
|
||||
compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {}
|
||||
|
||||
template <class A>
|
||||
explicit compressed_pair_1(const A& val)
|
||||
{
|
||||
init_one<best_convertion_traits<A, T1, T2>::value>::init(val, &_first, static_cast<T2*>(this));
|
||||
init_one<best_conversion_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_const_reference first() const { return _first; }
|
||||
|
||||
@@ -178,9 +211,20 @@ public:
|
||||
template <class A>
|
||||
explicit compressed_pair_2(const A& val)
|
||||
{
|
||||
init_one<best_convertion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), &_second);
|
||||
init_one<best_conversion_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_const_reference first() const { return *this; }
|
||||
|
||||
@@ -214,8 +258,10 @@ public:
|
||||
template <class A>
|
||||
explicit compressed_pair_3(const A& val)
|
||||
{
|
||||
init_one<best_convertion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), static_cast<T2*>(this));
|
||||
init_one<best_conversion_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_const_reference first() const { return *this; }
|
||||
@@ -247,6 +293,8 @@ public:
|
||||
compressed_pair_4(first_param_type x, second_param_type) : T1(x) {}
|
||||
// only one single argument constructor since T1 == T2
|
||||
explicit compressed_pair_4(first_param_type x) : T1(x) {}
|
||||
compressed_pair_4(const ::boost::compressed_pair<T1,T2>& x)
|
||||
: T1(x.first()){}
|
||||
|
||||
first_reference first() { return *this; }
|
||||
first_const_reference first() const { return *this; }
|
||||
@@ -280,7 +328,9 @@ public:
|
||||
compressed_pair_5() : _first(), _second() {}
|
||||
compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {}
|
||||
// only one single argument constructor since T1 == T2
|
||||
explicit compressed_pair_5(first_param_type x) : _first(x), _second() {}
|
||||
explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {}
|
||||
compressed_pair_5(const ::boost::compressed_pair<T1,T2>& c)
|
||||
: _first(c.first()), _second(c.second()) {}
|
||||
|
||||
first_reference first() { return _first; }
|
||||
first_const_reference first() const { return _first; }
|
||||
@@ -453,3 +503,4 @@ inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
|
||||
#endif // BOOST_OB_COMPRESSED_PAIR_HPP
|
||||
|
||||
|
||||
|
||||
|
27
iter_adaptor_fail_expected1.cpp
Normal file
27
iter_adaptor_fail_expected1.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
// Test boost/pending/iterator_adaptors.hpp
|
||||
|
||||
// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 21 Jan 01 Initial version (Jeremy Siek)
|
||||
|
||||
#include <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;
|
||||
}
|
28
iter_adaptor_fail_expected2.cpp
Normal file
28
iter_adaptor_fail_expected2.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
// Test boost/pending/iterator_adaptors.hpp
|
||||
|
||||
// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 21 Jan 01 Initial version (Jeremy Siek)
|
||||
|
||||
#include <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;
|
||||
}
|
32
iter_adaptor_fail_expected3.cpp
Normal file
32
iter_adaptor_fail_expected3.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
// 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,6 +9,26 @@
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// 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)
|
||||
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
|
||||
|
||||
@@ -17,13 +37,17 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <boost/pending/iterator_adaptors.hpp>
|
||||
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
#include <boost/pending/iterator_tests.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 { };
|
||||
|
||||
|
||||
using boost::dummyT;
|
||||
|
||||
struct my_iter_traits {
|
||||
@@ -42,9 +66,12 @@ struct my_const_iter_traits {
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
};
|
||||
|
||||
typedef boost::iterator_adaptors
|
||||
<dummyT*, const dummyT*,
|
||||
my_iter_traits, my_const_iter_traits> My;
|
||||
typedef boost::iterator_adaptor<dummyT*,
|
||||
boost::default_iterator_policies, my_iter_traits> my_iterator;
|
||||
|
||||
typedef boost::iterator_adaptor<const dummyT*,
|
||||
boost::default_iterator_policies, my_const_iter_traits> const_my_iterator;
|
||||
|
||||
|
||||
struct mult_functor {
|
||||
typedef int result_type;
|
||||
@@ -71,6 +98,88 @@ 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
|
||||
main()
|
||||
{
|
||||
@@ -81,12 +190,21 @@ main()
|
||||
// sanity check, if this doesn't pass the test is buggy
|
||||
boost::random_access_iterator_test(array,N,array);
|
||||
|
||||
// Test the iterator_adaptors
|
||||
// Check that the policy concept checks and the default policy
|
||||
// implementation match up.
|
||||
boost::function_requires<
|
||||
boost::RandomAccessIteratorPoliciesConcept<
|
||||
boost::default_iterator_policies, int*,
|
||||
boost::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t,
|
||||
int*, int&>
|
||||
> >();
|
||||
|
||||
// Test the iterator_adaptor
|
||||
{
|
||||
My::iterator i = array;
|
||||
my_iterator i = array;
|
||||
boost::random_access_iterator_test(i, N, array);
|
||||
|
||||
My::const_iterator j = array;
|
||||
const_my_iterator j = array;
|
||||
boost::random_access_iterator_test(j, N, array);
|
||||
boost::const_nonconst_iterator_test(i, ++j);
|
||||
}
|
||||
@@ -100,69 +218,134 @@ main()
|
||||
for (int k2 = 0; k2 < N; ++k2)
|
||||
x[k2] = x[k2] * 2;
|
||||
|
||||
boost::transform_iterator<mult_functor, int*,
|
||||
boost::iterator<std::random_access_iterator_tag,int> >::type
|
||||
boost::transform_iterator_generator<mult_functor, int*>::type
|
||||
i(y, mult_functor(2));
|
||||
boost::random_access_iterator_test(i, N, x);
|
||||
boost::input_iterator_test(i, x[0], x[1]);
|
||||
boost::input_iterator_test(boost::make_transform_iterator(&y[0], mult_functor(2)), x[0], x[1]);
|
||||
}
|
||||
// Test indirect_iterators
|
||||
|
||||
// Test indirect_iterator_generator
|
||||
{
|
||||
dummyT* ptr[N];
|
||||
for (int k = 0; k < N; ++k)
|
||||
ptr[k] = array + k;
|
||||
typedef boost::indirect_iterators<dummyT**, dummyT*, const dummyT*,
|
||||
boost::iterator<std::random_access_iterator_tag, dummyT*>,
|
||||
boost::iterator<std::random_access_iterator_tag, dummyT>,
|
||||
boost::iterator<std::random_access_iterator_tag, const dummyT>
|
||||
> Indirect;
|
||||
Indirect::iterator i = ptr;
|
||||
|
||||
typedef boost::indirect_iterator_generator<dummyT**
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
, dummyT
|
||||
#endif
|
||||
>::type indirect_iterator;
|
||||
|
||||
typedef boost::indirect_iterator_generator<dummyT**, const dummyT>::type const_indirect_iterator;
|
||||
|
||||
indirect_iterator i = ptr;
|
||||
boost::random_access_iterator_test(i, N, array);
|
||||
|
||||
Indirect::const_iterator j = ptr;
|
||||
boost::random_access_iterator_test(boost::make_indirect_iterator<dummyT>(ptr), N, array);
|
||||
|
||||
const_indirect_iterator j = ptr;
|
||||
boost::random_access_iterator_test(j, N, array);
|
||||
|
||||
boost::const_nonconst_iterator_test(i, ++j);
|
||||
dummyT*const* const_ptr = ptr;
|
||||
|
||||
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;
|
||||
Pair pair_array[N];
|
||||
for (int k = 0; k < N; ++k)
|
||||
pair_array[k].first = array[k];
|
||||
|
||||
typedef boost::projection_iterators<select1st_<Pair>,
|
||||
Pair*, const Pair*,
|
||||
boost::iterator<std::random_access_iterator_tag, Pair>,
|
||||
boost::iterator<std::random_access_iterator_tag, const Pair>
|
||||
typedef boost::projection_iterator_pair_generator<select1st_<Pair>,
|
||||
Pair*, const Pair*
|
||||
> Projection;
|
||||
|
||||
Projection::iterator i = pair_array;
|
||||
boost::random_access_iterator_test(i, N, array);
|
||||
|
||||
boost::random_access_iterator_test(boost::make_projection_iterator(pair_array, select1st_<Pair>()), N, array);
|
||||
boost::random_access_iterator_test(boost::make_projection_iterator< select1st_<Pair> >(pair_array), N, array);
|
||||
|
||||
Projection::const_iterator j = pair_array;
|
||||
boost::random_access_iterator_test(j, N, array);
|
||||
|
||||
boost::random_access_iterator_test(boost::make_const_projection_iterator(pair_array, select1st_<Pair>()), N, array);
|
||||
boost::random_access_iterator_test(boost::make_const_projection_iterator< select1st_<Pair> >(pair_array), N, array);
|
||||
|
||||
boost::const_nonconst_iterator_test(i, ++j);
|
||||
}
|
||||
// Test reverse_iterators
|
||||
// Test reverse_iterator_generator
|
||||
{
|
||||
dummyT reversed[N];
|
||||
std::copy(array, array + N, reversed);
|
||||
std::reverse(reversed, reversed + N);
|
||||
|
||||
typedef boost::reverse_iterators<dummyT*, const dummyT*,
|
||||
boost::iterator<std::random_access_iterator_tag,dummyT>,
|
||||
boost::iterator<std::random_access_iterator_tag,const dummyT>
|
||||
> Reverse;
|
||||
Reverse::iterator i = reversed + N;
|
||||
typedef boost::reverse_iterator_generator<dummyT*
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
, dummyT
|
||||
#endif
|
||||
>::type reverse_iterator;
|
||||
|
||||
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);
|
||||
|
||||
Reverse::const_iterator j = reversed + N;
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
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);
|
||||
|
||||
const dummyT* const_reversed = reversed;
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
|
||||
#endif
|
||||
|
||||
boost::const_nonconst_iterator_test(i, ++j);
|
||||
}
|
||||
|
||||
// Test reverse_iterator_generator again, with traits fully deducible on 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
|
||||
{
|
||||
int int_array[] = { 0, 1, 2, 3, 4, 5 };
|
||||
@@ -170,7 +353,33 @@ main()
|
||||
boost::random_access_iterator_test(r.begin(), r.size(), int_array);
|
||||
}
|
||||
|
||||
std::cout << "test successful " << std::endl;
|
||||
// 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;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -98,18 +98,28 @@ 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
|
||||
the iterator adaptor. The policy class determines how your new adaptor
|
||||
class will behave. The <tt>Policies</tt> class must implement 3, 4, or
|
||||
7 of the core iterator operations depending on whether you wish the
|
||||
the iterator adaptor, supplying the core iterator operations that will determine how your new adaptor
|
||||
class will behave. The core iterator operations are:
|
||||
<ul>
|
||||
<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
|
||||
<a href="http://www.sgi.com/Technology/STL/ForwardIterator.html">
|
||||
ForwardIterator</a>,
|
||||
<a href="http://www.sgi.com/Technology/STL/BidirectionalIterator.html">
|
||||
BidirectionalIterator</a>, or <a
|
||||
href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">
|
||||
RandomAccessIterator</a>. Make sure that the
|
||||
RandomAccessIterator</a>. The
|
||||
<tt>iterator_category</tt> type of the traits class you pass in
|
||||
matches the category of iterator that you want to create. The default
|
||||
must match the category of iterator that you want to create. The default
|
||||
policy class, <tt>default_iterator_policies</tt>, implements all 7 of
|
||||
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,
|
||||
@@ -797,7 +807,7 @@ uses the three adaptors.
|
||||
|
||||
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->27 Nov 2000<!--webbot bot="Timestamp" endspan i-checksum="15248" --></p>
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->10 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14373" --></p>
|
||||
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
|
||||
modify, sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is"
|
||||
|
155
iterator_traits_test.cpp
Normal file
155
iterator_traits_test.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
// (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;
|
||||
}
|
385
numeric_traits_test.cpp
Normal file
385
numeric_traits_test.cpp
Normal file
@@ -0,0 +1,385 @@
|
||||
// (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
|
||||
usage idiom while allowing the library remain backward-compatible.</p>
|
||||
<hr>
|
||||
<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>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><EFBFBD> Copyright David Abrahams and Beman Dawes 1999-2000. Permission to copy,
|
||||
use, modify, sell and distribute this document is granted provided this
|
||||
copyright notice appears in all copies. This document is provided "as
|
||||
|
@@ -7,14 +7,24 @@
|
||||
// standalone test program for <boost/type_traits.hpp>
|
||||
|
||||
/* 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:
|
||||
Added extra tests for is_empty, is_convertible, alignment_of.
|
||||
23rd July 2000:
|
||||
Removed all call_traits tests to call_traits_test.cpp
|
||||
Removed all compressed_pair tests to compressed_pair_tests.cpp
|
||||
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 <typeinfo>
|
||||
@@ -140,7 +150,7 @@ template <> struct is_POD<empty_POD_union_UDT>
|
||||
|
||||
class Base { };
|
||||
|
||||
class Deriverd : public Base { };
|
||||
class Derived : public Base { };
|
||||
|
||||
class NonDerived { };
|
||||
|
||||
@@ -182,19 +192,32 @@ struct non_empty : boost::noncopyable
|
||||
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:" 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
|
||||
// compiler hints only. These failures should be fixed before long.
|
||||
|
||||
int main()
|
||||
int main(int, char*[])
|
||||
{
|
||||
std::cout << "Checking type operations..." << std::endl << std::endl;
|
||||
|
||||
// cv-qualifiers applied to reference types should have no effect
|
||||
// declare these here for later use with is_reference and remove_reference:
|
||||
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;
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
type_test(int, remove_reference<int>::type)
|
||||
type_test(const int, remove_reference<const int>::type)
|
||||
@@ -232,6 +255,9 @@ int main()
|
||||
|
||||
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(false, (is_same<int, const int>::value))
|
||||
value_test(false, (is_same<int, int&>::value))
|
||||
@@ -391,6 +417,7 @@ int main()
|
||||
value_test(true, is_array<int[2][3]>::value)
|
||||
value_test(true, is_array<UDT[2]>::value)
|
||||
value_test(false, is_array<int(&)[2]>::value)
|
||||
value_test(true, is_array<const int[2]>::value)
|
||||
|
||||
typedef void(*f1)();
|
||||
typedef int(*f2)(int);
|
||||
@@ -583,11 +610,13 @@ int main()
|
||||
value_test(false, is_POD<empty_UDT>::value)
|
||||
value_test(true, is_POD<enum_UDT>::value)
|
||||
|
||||
value_test(true, (boost::is_convertible<Deriverd,Base>::value));
|
||||
value_test(true, (boost::is_convertible<Deriverd,Deriverd>::value));
|
||||
value_test(true, (boost::is_convertible<implicitly_convertible_to_int,
|
||||
int>::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(false, (boost::is_convertible<Base,Deriverd>::value));
|
||||
value_test(true, (boost::is_convertible<Deriverd,Deriverd>::value));
|
||||
value_test(false, (boost::is_convertible<Base,Derived>::value));
|
||||
value_test(true, (boost::is_convertible<Derived,Derived>::value));
|
||||
value_test(false, (boost::is_convertible<NonDerived,Base>::value));
|
||||
value_test(false, (boost::is_convertible<boost::noncopyable, int>::value));
|
||||
value_test(true, (boost::is_convertible<float,int>::value));
|
||||
@@ -597,14 +626,14 @@ int main()
|
||||
value_test(true, (boost::is_convertible<void,void>::value));
|
||||
#endif
|
||||
value_test(true, (boost::is_convertible<enum1, int>::value));
|
||||
value_test(true, (boost::is_convertible<Deriverd*, Base*>::value));
|
||||
value_test(false, (boost::is_convertible<Base*, Deriverd*>::value));
|
||||
value_test(true, (boost::is_convertible<Deriverd&, Base&>::value));
|
||||
value_test(false, (boost::is_convertible<Base&, Deriverd&>::value));
|
||||
value_test(true, (boost::is_convertible<const Deriverd*, const Base*>::value));
|
||||
value_test(false, (boost::is_convertible<const Base*, const Deriverd*>::value));
|
||||
value_test(true, (boost::is_convertible<const Deriverd&, const Base&>::value));
|
||||
value_test(false, (boost::is_convertible<const Base&, const Deriverd&>::value));
|
||||
value_test(true, (boost::is_convertible<Derived*, Base*>::value));
|
||||
value_test(false, (boost::is_convertible<Base*, Derived*>::value));
|
||||
value_test(true, (boost::is_convertible<Derived&, Base&>::value));
|
||||
value_test(false, (boost::is_convertible<Base&, Derived&>::value));
|
||||
value_test(true, (boost::is_convertible<const Derived*, const Base*>::value));
|
||||
value_test(false, (boost::is_convertible<const Base*, const Derived*>::value));
|
||||
value_test(true, (boost::is_convertible<const Derived&, const Base&>::value));
|
||||
value_test(false, (boost::is_convertible<const Base&, const Derived&>::value));
|
||||
|
||||
value_test(false, (boost::is_convertible<const int *, int*>::value));
|
||||
value_test(false, (boost::is_convertible<const int&, int&>::value));
|
||||
@@ -634,8 +663,7 @@ int main()
|
||||
align_test(VB);
|
||||
align_test(VD);
|
||||
|
||||
std::cout << std::endl << test_count << " tests completed (" << failures << " failures)... press any key to exit";
|
||||
std::cin.get();
|
||||
std::cout << std::endl << test_count << " tests completed (" << failures << " 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
|
||||
// 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.
|
||||
// (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// common test code for type_traits_test.cpp/call_traits_test.cpp/compressed_pair_test.cpp
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
#ifndef 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:
|
||||
//
|
||||
@@ -94,8 +98,6 @@ struct test_align<T&>
|
||||
|
||||
//
|
||||
// define tests here
|
||||
unsigned failures = 0;
|
||||
unsigned test_count = 0;
|
||||
|
||||
//
|
||||
// turn off some warnings:
|
||||
|
Reference in New Issue
Block a user