1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
|
// (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 Mar 2001 Patches for Intel C++ (Dave Abrahams)
// 19 Feb 2001 Take advantage of improved iterator_traits to do more tests
// on MSVC. Reordered some #ifdefs for coherency.
// (David Abrahams)
// 13 Feb 2001 Test new VC6 workarounds (David Abrahams)
// 11 Feb 2001 Final fixes for Borland (David Abrahams)
// 11 Feb 2001 Some fixes for Borland get it closer on that compiler
// (David Abrahams)
// 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>
// An iterator for which we can get traits.
struct my_iterator1
: boost::forward_iterator_helper<my_iterator1, char, long, const char*, const char&>
{
my_iterator1(const char* p) : m_p(p) {}
bool operator==(const my_iterator1& rhs) const
{ return this->m_p == rhs.m_p; }
my_iterator1& operator++() { ++this->m_p; return *this; }
const char& operator*() { return *m_p; }
private:
const char* m_p;
};
// Used to prove that we don't require std::iterator<> in the hierarchy under
// MSVC6, and that we can compute all the traits for a standard-conforming UDT
// iterator.
struct my_iterator2
: boost::equality_comparable<my_iterator2
, boost::incrementable<my_iterator2
, boost::dereferenceable<my_iterator2,const char*> > >
{
typedef char value_type;
typedef long difference_type;
typedef const char* pointer;
typedef const char& reference;
typedef std::forward_iterator_tag iterator_category;
my_iterator2(const char* p) : m_p(p) {}
bool operator==(const my_iterator2& rhs) const
{ return this->m_p == rhs.m_p; }
my_iterator2& operator++() { ++this->m_p; return *this; }
const char& operator*() { return *m_p; }
private:
const char* m_p;
};
// Used to prove that we're not overly confused by the existence of
// std::iterator<> in the hierarchy under MSVC6 - we should find that
// boost::detail::iterator_traits<my_iterator3>::difference_type is int.
struct my_iterator3 : my_iterator1
{
typedef int difference_type;
my_iterator3(const char* p) : my_iterator1(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>
, non_portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
{
};
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;
//
#if defined(__BORLANDC__) && !defined(__SGI_STL_PORT)
typedef ::std::char_traits<char>::off_type distance;
non_pointer_test<std::ostream_iterator<int>,int,
distance,int*,int&,std::output_iterator_tag> ostream_iterator_test;
#elif defined(BOOST_MSVC_STD_ITERATOR)
non_pointer_test<std::ostream_iterator<int>,
int, void, void, void, std::output_iterator_tag>
ostream_iterator_test;
#else
non_pointer_test<std::ostream_iterator<int>,
void, void, void, void, std::output_iterator_tag>
ostream_iterator_test;
#endif
#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_iterator1, char, long, const char*, const char&, std::forward_iterator_tag>
my_iterator1_test;
non_pointer_test<my_iterator2, char, long, const char*, const char&, std::forward_iterator_tag>
my_iterator2_test;
non_pointer_test<my_iterator3, char, int, const char*, const char&, std::forward_iterator_tag>
my_iterator3_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_iterator1(chars), my_iterator1(chars + length)) == length);
assert(boost::detail::distance(my_iterator2(chars), my_iterator2(chars + length)) == length);
assert(boost::detail::distance(my_iterator3(chars), my_iterator3(chars + length)) == length);
}
return 0;
}
|