mirror of
				https://github.com/boostorg/utility.git
				synced 2025-11-04 02:11:45 +01:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			svn-branch
			...
			svn-branch
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					e608036e99 | ||
| 
						 | 
					91c135c0af | 
@@ -1,53 +0,0 @@
 | 
			
		||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears
 | 
			
		||||
// in all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <boost/counting_iterator.hpp>
 | 
			
		||||
#include <boost/iterator_adaptors.hpp>
 | 
			
		||||
 | 
			
		||||
int main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  // Example of using counting_iterator_generator
 | 
			
		||||
  std::cout << "counting from 0 to 4:" << std::endl;
 | 
			
		||||
  boost::counting_iterator_generator<int>::type first(0), last(4);
 | 
			
		||||
  std::copy(first, last, std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // Example of using make_counting_iterator()
 | 
			
		||||
  std::cout << "counting from -5 to 4:" << std::endl;
 | 
			
		||||
  std::copy(boost::make_counting_iterator(-5),
 | 
			
		||||
	    boost::make_counting_iterator(5),
 | 
			
		||||
	    std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // Example of using counting iterator to create an array of pointers.
 | 
			
		||||
  const int N = 7;
 | 
			
		||||
  std::vector<int> numbers;
 | 
			
		||||
  // Fill "numbers" array with [0,N)
 | 
			
		||||
  std::copy(boost::make_counting_iterator(0), boost::make_counting_iterator(N),
 | 
			
		||||
	    std::back_inserter(numbers));
 | 
			
		||||
 | 
			
		||||
  std::vector<std::vector<int>::iterator> pointers;
 | 
			
		||||
 | 
			
		||||
  // Use counting iterator to fill in the array of pointers.
 | 
			
		||||
  std::copy(boost::make_counting_iterator(numbers.begin()),
 | 
			
		||||
	    boost::make_counting_iterator(numbers.end()),
 | 
			
		||||
	    std::back_inserter(pointers));
 | 
			
		||||
 | 
			
		||||
  // Use indirect iterator to print out numbers by accessing
 | 
			
		||||
  // them through the array of pointers.
 | 
			
		||||
  std::cout << "indirectly printing out the numbers from 0 to " 
 | 
			
		||||
	    << N << std::endl;
 | 
			
		||||
  std::copy(boost::make_indirect_iterator(pointers.begin()),
 | 
			
		||||
	    boost::make_indirect_iterator(pointers.end()),
 | 
			
		||||
	    std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,428 +0,0 @@
 | 
			
		||||
//  (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & 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.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
// compressed_pair: pair that "compresses" empty members
 | 
			
		||||
// (see libs/utility/compressed_pair.htm)
 | 
			
		||||
//
 | 
			
		||||
// JM changes 25 Jan 2000:
 | 
			
		||||
// Removed default arguments from compressed_pair_switch to get
 | 
			
		||||
// C++ Builder 4 to accept them
 | 
			
		||||
// rewriten swap to get gcc and C++ builder to compile.
 | 
			
		||||
// added partial specialisations for case T1 == T2 to avoid duplicate constructor defs.
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_DETAIL_COMPRESSED_PAIR_HPP
 | 
			
		||||
#define BOOST_DETAIL_COMPRESSED_PAIR_HPP
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#ifndef BOOST_OBJECT_TYPE_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits/object_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOST_SAME_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits/same_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOST_CALL_TRAITS_HPP
 | 
			
		||||
#include <boost/call_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
// compressed_pair
 | 
			
		||||
 | 
			
		||||
namespace details
 | 
			
		||||
{
 | 
			
		||||
   // JM altered 26 Jan 2000:
 | 
			
		||||
   template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty>
 | 
			
		||||
   struct compressed_pair_switch;
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   struct compressed_pair_switch<T1, T2, false, false, false>
 | 
			
		||||
      {static const int value = 0;};
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   struct compressed_pair_switch<T1, T2, false, true, true>
 | 
			
		||||
      {static const int value = 3;};
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   struct compressed_pair_switch<T1, T2, false, true, false>
 | 
			
		||||
      {static const int value = 1;};
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   struct compressed_pair_switch<T1, T2, false, false, true>
 | 
			
		||||
      {static const int value = 2;};
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   struct compressed_pair_switch<T1, T2, true, true, true>
 | 
			
		||||
      {static const int value = 4;};
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   struct compressed_pair_switch<T1, T2, true, false, false>
 | 
			
		||||
      {static const int value = 5;};
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2, int Version> class compressed_pair_imp;
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
   // workaround for GCC (JM):
 | 
			
		||||
   using std::swap;
 | 
			
		||||
#endif
 | 
			
		||||
   //
 | 
			
		||||
   // can't call unqualified swap from within classname::swap
 | 
			
		||||
   // as Koenig lookup rules will find only the classname::swap
 | 
			
		||||
   // member function not the global declaration, so use cp_swap
 | 
			
		||||
   // as a forwarding function (JM):
 | 
			
		||||
   template <typename T>
 | 
			
		||||
   inline void cp_swap(T& t1, T& t2)
 | 
			
		||||
   {
 | 
			
		||||
#ifndef __GNUC__
 | 
			
		||||
      using std::swap;
 | 
			
		||||
#endif
 | 
			
		||||
      swap(t1, t2);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   // 0    derive from neither
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   class compressed_pair_imp<T1, T2, 0>
 | 
			
		||||
   {
 | 
			
		||||
   public:
 | 
			
		||||
      typedef T1                                                 first_type;
 | 
			
		||||
      typedef T2                                                 second_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
      typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
      typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp() {} 
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(first_param_type x, second_param_type y)
 | 
			
		||||
         : first_(x), second_(y) {}
 | 
			
		||||
 | 
			
		||||
      explicit compressed_pair_imp(first_param_type x)
 | 
			
		||||
         : first_(x) {}
 | 
			
		||||
 | 
			
		||||
      explicit compressed_pair_imp(second_param_type y)
 | 
			
		||||
         : second_(y) {}
 | 
			
		||||
 | 
			
		||||
      first_reference       first()       {return first_;}
 | 
			
		||||
      first_const_reference first() const {return first_;}
 | 
			
		||||
 | 
			
		||||
      second_reference       second()       {return second_;}
 | 
			
		||||
      second_const_reference second() const {return second_;}
 | 
			
		||||
 | 
			
		||||
      void swap(compressed_pair_imp& y)
 | 
			
		||||
      {
 | 
			
		||||
         cp_swap(first_, y.first_);
 | 
			
		||||
         cp_swap(second_, y.second_);
 | 
			
		||||
      }
 | 
			
		||||
   private:
 | 
			
		||||
      first_type first_;
 | 
			
		||||
      second_type second_;
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
   // 1    derive from T1
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   class compressed_pair_imp<T1, T2, 1>
 | 
			
		||||
      : private T1
 | 
			
		||||
   {
 | 
			
		||||
   public:
 | 
			
		||||
      typedef T1                                                 first_type;
 | 
			
		||||
      typedef T2                                                 second_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
      typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
      typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp() {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(first_param_type x, second_param_type y)
 | 
			
		||||
         : first_type(x), second_(y) {}
 | 
			
		||||
 | 
			
		||||
      explicit compressed_pair_imp(first_param_type x)
 | 
			
		||||
         : first_type(x) {}
 | 
			
		||||
 | 
			
		||||
      explicit compressed_pair_imp(second_param_type y)
 | 
			
		||||
         : second_(y) {}
 | 
			
		||||
 | 
			
		||||
      first_reference       first()       {return *this;}
 | 
			
		||||
      first_const_reference first() const {return *this;}
 | 
			
		||||
 | 
			
		||||
      second_reference       second()       {return second_;}
 | 
			
		||||
      second_const_reference second() const {return second_;}
 | 
			
		||||
 | 
			
		||||
      void swap(compressed_pair_imp& y)
 | 
			
		||||
      {
 | 
			
		||||
         // no need to swap empty base class:
 | 
			
		||||
         cp_swap(second_, y.second_);
 | 
			
		||||
      }
 | 
			
		||||
   private:
 | 
			
		||||
      second_type second_;
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
   // 2    derive from T2
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   class compressed_pair_imp<T1, T2, 2>
 | 
			
		||||
      : private T2
 | 
			
		||||
   {
 | 
			
		||||
   public:
 | 
			
		||||
      typedef T1                                                 first_type;
 | 
			
		||||
      typedef T2                                                 second_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
      typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
      typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp() {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(first_param_type x, second_param_type y)
 | 
			
		||||
         : second_type(y), first_(x) {}
 | 
			
		||||
 | 
			
		||||
      explicit compressed_pair_imp(first_param_type x)
 | 
			
		||||
         : first_(x) {}
 | 
			
		||||
 | 
			
		||||
      explicit compressed_pair_imp(second_param_type y)
 | 
			
		||||
         : second_type(y) {}
 | 
			
		||||
 | 
			
		||||
      first_reference       first()       {return first_;}
 | 
			
		||||
      first_const_reference first() const {return first_;}
 | 
			
		||||
 | 
			
		||||
      second_reference       second()       {return *this;}
 | 
			
		||||
      second_const_reference second() const {return *this;}
 | 
			
		||||
 | 
			
		||||
      void swap(compressed_pair_imp& y)
 | 
			
		||||
      {
 | 
			
		||||
         // no need to swap empty base class:
 | 
			
		||||
         cp_swap(first_, y.first_);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
   private:
 | 
			
		||||
      first_type first_;
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
   // 3    derive from T1 and T2
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   class compressed_pair_imp<T1, T2, 3>
 | 
			
		||||
      : private T1,
 | 
			
		||||
        private T2
 | 
			
		||||
   {
 | 
			
		||||
   public:
 | 
			
		||||
      typedef T1                                                 first_type;
 | 
			
		||||
      typedef T2                                                 second_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
      typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
      typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp() {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(first_param_type x, second_param_type y)
 | 
			
		||||
         : first_type(x), second_type(y) {}
 | 
			
		||||
 | 
			
		||||
      explicit compressed_pair_imp(first_param_type x)
 | 
			
		||||
         : first_type(x) {}
 | 
			
		||||
 | 
			
		||||
      explicit compressed_pair_imp(second_param_type y)
 | 
			
		||||
         : second_type(y) {}
 | 
			
		||||
 | 
			
		||||
      first_reference       first()       {return *this;}
 | 
			
		||||
      first_const_reference first() const {return *this;}
 | 
			
		||||
 | 
			
		||||
      second_reference       second()       {return *this;}
 | 
			
		||||
      second_const_reference second() const {return *this;}
 | 
			
		||||
      //
 | 
			
		||||
      // no need to swap empty bases:
 | 
			
		||||
      void swap(compressed_pair_imp&) {}
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
   // JM
 | 
			
		||||
   // 4    T1 == T2, T1 and T2 both empty
 | 
			
		||||
   //      Note does not actually store an instance of T2 at all -
 | 
			
		||||
   //      but reuses T1 base class for both first() and second().
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   class compressed_pair_imp<T1, T2, 4>
 | 
			
		||||
      : private T1
 | 
			
		||||
   {
 | 
			
		||||
   public:
 | 
			
		||||
      typedef T1                                                 first_type;
 | 
			
		||||
      typedef T2                                                 second_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
      typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
      typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp() {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(first_param_type x, second_param_type)
 | 
			
		||||
         : first_type(x) {}
 | 
			
		||||
 | 
			
		||||
      explicit compressed_pair_imp(first_param_type x)
 | 
			
		||||
         : first_type(x) {}
 | 
			
		||||
 | 
			
		||||
      first_reference       first()       {return *this;}
 | 
			
		||||
      first_const_reference first() const {return *this;}
 | 
			
		||||
 | 
			
		||||
      second_reference       second()       {return *this;}
 | 
			
		||||
      second_const_reference second() const {return *this;}
 | 
			
		||||
 | 
			
		||||
      void swap(compressed_pair_imp&) {}
 | 
			
		||||
   private:
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
   // 5    T1 == T2 and are not empty:   //JM
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   class compressed_pair_imp<T1, T2, 5>
 | 
			
		||||
   {
 | 
			
		||||
   public:
 | 
			
		||||
      typedef T1                                                 first_type;
 | 
			
		||||
      typedef T2                                                 second_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
      typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
      typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp() {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(first_param_type x, second_param_type y)
 | 
			
		||||
         : first_(x), second_(y) {}
 | 
			
		||||
 | 
			
		||||
      explicit compressed_pair_imp(first_param_type x)
 | 
			
		||||
         : first_(x), second_(x) {}
 | 
			
		||||
 | 
			
		||||
      first_reference       first()       {return first_;}
 | 
			
		||||
      first_const_reference first() const {return first_;}
 | 
			
		||||
 | 
			
		||||
      second_reference       second()       {return second_;}
 | 
			
		||||
      second_const_reference second() const {return second_;}
 | 
			
		||||
 | 
			
		||||
      void swap(compressed_pair_imp<T1, T2, 5>& y)
 | 
			
		||||
      {
 | 
			
		||||
         cp_swap(first_, y.first_);
 | 
			
		||||
         cp_swap(second_, y.second_);
 | 
			
		||||
      }
 | 
			
		||||
   private:
 | 
			
		||||
      first_type first_;
 | 
			
		||||
      second_type second_;
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
}  // details
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
class compressed_pair
 | 
			
		||||
   : private ::boost::details::compressed_pair_imp<T1, T2,
 | 
			
		||||
             ::boost::details::compressed_pair_switch<
 | 
			
		||||
                    T1,
 | 
			
		||||
                    T2,
 | 
			
		||||
                    ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
 | 
			
		||||
                    ::boost::is_empty<T1>::value,
 | 
			
		||||
                    ::boost::is_empty<T2>::value>::value>
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
   typedef details::compressed_pair_imp<T1, T2,
 | 
			
		||||
             ::boost::details::compressed_pair_switch<
 | 
			
		||||
                    T1,
 | 
			
		||||
                    T2,
 | 
			
		||||
                    ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
 | 
			
		||||
                    ::boost::is_empty<T1>::value,
 | 
			
		||||
                    ::boost::is_empty<T2>::value>::value> base;
 | 
			
		||||
public:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
   typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
            compressed_pair() : base() {}
 | 
			
		||||
            compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
 | 
			
		||||
   explicit compressed_pair(first_param_type x) : base(x) {}
 | 
			
		||||
   explicit compressed_pair(second_param_type y) : base(y) {}
 | 
			
		||||
 | 
			
		||||
   first_reference       first()       {return base::first();}
 | 
			
		||||
   first_const_reference first() const {return base::first();}
 | 
			
		||||
 | 
			
		||||
   second_reference       second()       {return base::second();}
 | 
			
		||||
   second_const_reference second() const {return base::second();}
 | 
			
		||||
 | 
			
		||||
   void swap(compressed_pair& y) { base::swap(y); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// JM
 | 
			
		||||
// Partial specialisation for case where T1 == T2:
 | 
			
		||||
//
 | 
			
		||||
template <class T>
 | 
			
		||||
class compressed_pair<T, T>
 | 
			
		||||
   : private details::compressed_pair_imp<T, T,
 | 
			
		||||
             ::boost::details::compressed_pair_switch<
 | 
			
		||||
                    T,
 | 
			
		||||
                    T,
 | 
			
		||||
                    ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
 | 
			
		||||
                    ::boost::is_empty<T>::value,
 | 
			
		||||
                    ::boost::is_empty<T>::value>::value>
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
   typedef details::compressed_pair_imp<T, T,
 | 
			
		||||
             ::boost::details::compressed_pair_switch<
 | 
			
		||||
                    T,
 | 
			
		||||
                    T,
 | 
			
		||||
                    ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
 | 
			
		||||
                    ::boost::is_empty<T>::value,
 | 
			
		||||
                    ::boost::is_empty<T>::value>::value> base;
 | 
			
		||||
public:
 | 
			
		||||
   typedef T                                                  first_type;
 | 
			
		||||
   typedef T                                                  second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
   typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
            compressed_pair() : base() {}
 | 
			
		||||
            compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
 | 
			
		||||
   explicit compressed_pair(first_param_type x) : base(x) {}
 | 
			
		||||
 | 
			
		||||
   first_reference       first()       {return base::first();}
 | 
			
		||||
   first_const_reference first() const {return base::first();}
 | 
			
		||||
 | 
			
		||||
   second_reference       second()       {return base::second();}
 | 
			
		||||
   second_const_reference second() const {return base::second();}
 | 
			
		||||
 | 
			
		||||
   void swap(compressed_pair& y) { base::swap(y); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
inline
 | 
			
		||||
void
 | 
			
		||||
swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
 | 
			
		||||
{
 | 
			
		||||
   x.swap(y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // boost
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -1,128 +0,0 @@
 | 
			
		||||
//  (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & 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.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
//
 | 
			
		||||
//  Crippled version for crippled compilers:
 | 
			
		||||
//  see libs/utility/call_traits.htm
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
/* Release notes:
 | 
			
		||||
   01st October 2000:
 | 
			
		||||
      Fixed call_traits on VC6, using "poor man's partial specialisation",
 | 
			
		||||
      using ideas taken from "Generative programming" by Krzysztof Czarnecki 
 | 
			
		||||
      & Ulrich Eisenecker.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_OB_CALL_TRAITS_HPP
 | 
			
		||||
#define BOOST_OB_CALL_TRAITS_HPP
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_CONFIG_HPP
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits/arithmetic_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOST_COMPOSITE_TYPE_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits/composite_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace boost{
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)
 | 
			
		||||
//
 | 
			
		||||
// use member templates to emulate
 | 
			
		||||
// partial specialisation:
 | 
			
		||||
//
 | 
			
		||||
namespace detail{
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
struct standard_call_traits
 | 
			
		||||
{
 | 
			
		||||
   typedef T value_type;
 | 
			
		||||
   typedef T& reference;
 | 
			
		||||
   typedef const T& const_reference;
 | 
			
		||||
   typedef const T& param_type;
 | 
			
		||||
};
 | 
			
		||||
template <class T>
 | 
			
		||||
struct simple_call_traits
 | 
			
		||||
{
 | 
			
		||||
   typedef T value_type;
 | 
			
		||||
   typedef T& reference;
 | 
			
		||||
   typedef const T& const_reference;
 | 
			
		||||
   typedef const T param_type;
 | 
			
		||||
};
 | 
			
		||||
template <class T>
 | 
			
		||||
struct reference_call_traits
 | 
			
		||||
{
 | 
			
		||||
   typedef T value_type;
 | 
			
		||||
   typedef T reference;
 | 
			
		||||
   typedef T const_reference;
 | 
			
		||||
   typedef T param_type;
 | 
			
		||||
};
 | 
			
		||||
template <bool simple, bool reference>
 | 
			
		||||
struct call_traits_chooser
 | 
			
		||||
{
 | 
			
		||||
   template <class T>
 | 
			
		||||
   struct rebind
 | 
			
		||||
   {
 | 
			
		||||
      typedef standard_call_traits<T> type;
 | 
			
		||||
   };
 | 
			
		||||
};
 | 
			
		||||
template <>
 | 
			
		||||
struct call_traits_chooser<true, false>
 | 
			
		||||
{
 | 
			
		||||
   template <class T>
 | 
			
		||||
   struct rebind
 | 
			
		||||
   {
 | 
			
		||||
      typedef simple_call_traits<T> type;
 | 
			
		||||
   };
 | 
			
		||||
};
 | 
			
		||||
template <>
 | 
			
		||||
struct call_traits_chooser<false, true>
 | 
			
		||||
{
 | 
			
		||||
   template <class T>
 | 
			
		||||
   struct rebind
 | 
			
		||||
   {
 | 
			
		||||
      typedef reference_call_traits<T> type;
 | 
			
		||||
   };
 | 
			
		||||
};
 | 
			
		||||
} // namespace detail
 | 
			
		||||
template <typename T>
 | 
			
		||||
struct call_traits
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
   typedef detail::call_traits_chooser<(is_pointer<T>::value || is_arithmetic<T>::value) && sizeof(T) <= sizeof(void*), is_reference<T>::value> chooser;
 | 
			
		||||
   typedef typename chooser::template rebind<T> bound_type;
 | 
			
		||||
   typedef typename bound_type::type call_traits_type;
 | 
			
		||||
public:
 | 
			
		||||
   typedef typename call_traits_type::value_type       value_type;
 | 
			
		||||
   typedef typename call_traits_type::reference        reference;
 | 
			
		||||
   typedef typename call_traits_type::const_reference  const_reference;
 | 
			
		||||
   typedef typename call_traits_type::param_type       param_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
//
 | 
			
		||||
// sorry call_traits is completely non-functional
 | 
			
		||||
// blame your broken compiler:
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
struct call_traits
 | 
			
		||||
{
 | 
			
		||||
   typedef T value_type;
 | 
			
		||||
   typedef T& reference;
 | 
			
		||||
   typedef const T& const_reference;
 | 
			
		||||
   typedef const T& param_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // member templates
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_OB_CALL_TRAITS_HPP
 | 
			
		||||
							
								
								
									
										464
									
								
								iterator_adaptor_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										464
									
								
								iterator_adaptor_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,464 @@
 | 
			
		||||
//  Demonstrate and test boost/operators.hpp on std::iterators  -------------//
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
 | 
			
		||||
//  sell and distribute this software is granted provided this
 | 
			
		||||
//  copyright notice appears in all copies. This software is provided
 | 
			
		||||
//  "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
//  to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  04 Mar 01 Workaround for Borland (Dave Abrahams)
 | 
			
		||||
//  19 Feb 01 Take adavantage of improved iterator_traits to do more tests
 | 
			
		||||
//            on MSVC. Hack around an MSVC-with-STLport internal compiler
 | 
			
		||||
//            error. (David Abrahams)
 | 
			
		||||
//  11 Feb 01 Added test of operator-> for forward and input iterators.
 | 
			
		||||
//            (Jeremy Siek)
 | 
			
		||||
//  11 Feb 01 Borland fixes (David Abrahams)
 | 
			
		||||
//  10 Feb 01 Use new adaptors interface. (David Abrahams)
 | 
			
		||||
//  10 Feb 01 Use new filter_ interface. (David Abrahams)
 | 
			
		||||
//  09 Feb 01 Use new reverse_ and indirect_ interfaces. Replace
 | 
			
		||||
//            BOOST_NO_STD_ITERATOR_TRAITS with
 | 
			
		||||
//            BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION to prove we've
 | 
			
		||||
//            normalized to core compiler capabilities (David Abrahams)
 | 
			
		||||
//  08 Feb 01 Use Jeremy's new make_reverse_iterator form; add more
 | 
			
		||||
//            comprehensive testing. Force-decay array function arguments to
 | 
			
		||||
//            pointers.
 | 
			
		||||
//  07 Feb 01 Added tests for the make_xxx_iterator() helper functions.
 | 
			
		||||
//            (Jeremy Siek)
 | 
			
		||||
//  07 Feb 01 Replaced use of xxx_pair_generator with xxx_generator where
 | 
			
		||||
//            possible (which was all but the projection iterator).
 | 
			
		||||
//            (Jeremy Siek)
 | 
			
		||||
//  06 Feb 01 Removed now-defaulted template arguments where possible
 | 
			
		||||
//            Updated names to correspond to new generator naming convention.
 | 
			
		||||
//            Added a trivial test for make_transform_iterator().
 | 
			
		||||
//            Gave traits for const iterators a mutable value_type, per std.
 | 
			
		||||
//            Resurrected my original tests for indirect iterators.
 | 
			
		||||
//            (David Abrahams)
 | 
			
		||||
//  04 Feb 01 Fix for compilers without standard iterator_traits
 | 
			
		||||
//            (David Abrahams)
 | 
			
		||||
//  13 Jun 00 Added const version of the iterator tests (Jeremy Siek)
 | 
			
		||||
//  12 Dec 99 Initial version with iterator operators (Jeremy Siek)
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <functional>
 | 
			
		||||
 | 
			
		||||
#include <boost/iterator_adaptors.hpp>
 | 
			
		||||
#include <boost/pending/iterator_tests.hpp>
 | 
			
		||||
#include <boost/pending/integer_range.hpp>
 | 
			
		||||
#include <boost/concept_archetype.hpp>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <deque>
 | 
			
		||||
#include <set>
 | 
			
		||||
 | 
			
		||||
struct my_iterator_tag : public std::random_access_iterator_tag { };
 | 
			
		||||
 | 
			
		||||
using boost::dummyT;
 | 
			
		||||
 | 
			
		||||
struct my_iter_traits {
 | 
			
		||||
  typedef dummyT value_type;
 | 
			
		||||
  typedef dummyT* pointer;
 | 
			
		||||
  typedef dummyT& reference;
 | 
			
		||||
  typedef my_iterator_tag iterator_category;
 | 
			
		||||
  typedef std::ptrdiff_t difference_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct my_const_iter_traits {
 | 
			
		||||
  typedef dummyT value_type;
 | 
			
		||||
  typedef const dummyT* pointer;
 | 
			
		||||
  typedef const dummyT& reference;
 | 
			
		||||
  typedef my_iterator_tag iterator_category;
 | 
			
		||||
  typedef std::ptrdiff_t difference_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef boost::iterator_adaptor<dummyT*, 
 | 
			
		||||
  boost::default_iterator_policies, dummyT> my_iterator;
 | 
			
		||||
 | 
			
		||||
typedef boost::iterator_adaptor<const dummyT*, 
 | 
			
		||||
  boost::default_iterator_policies, const dummyT> const_my_iterator;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct mult_functor {
 | 
			
		||||
  typedef int result_type;
 | 
			
		||||
  typedef int argument_type;
 | 
			
		||||
  // Functors used with transform_iterator must be
 | 
			
		||||
  // DefaultConstructible, as the transform_iterator must be
 | 
			
		||||
  // DefaultConstructible to satisfy the requirements for
 | 
			
		||||
  // TrivialIterator.
 | 
			
		||||
  mult_functor() { }
 | 
			
		||||
  mult_functor(int aa) : a(aa) { }
 | 
			
		||||
  int operator()(int b) const { return a * b; }
 | 
			
		||||
  int a;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class Pair>
 | 
			
		||||
struct select1st_ 
 | 
			
		||||
  : public std::unary_function<Pair, typename Pair::first_type>
 | 
			
		||||
{
 | 
			
		||||
  const typename Pair::first_type& operator()(const Pair& x) const {
 | 
			
		||||
    return x.first;
 | 
			
		||||
  }
 | 
			
		||||
  typename Pair::first_type& operator()(Pair& x) const {
 | 
			
		||||
    return x.first;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct one_or_four {
 | 
			
		||||
  bool operator()(dummyT x) const {
 | 
			
		||||
    return x.foo() == 1 || x.foo() == 4;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef std::deque<int> storage;
 | 
			
		||||
typedef std::deque<int*> pointer_deque;
 | 
			
		||||
typedef std::set<storage::iterator> iterator_set;
 | 
			
		||||
 | 
			
		||||
void more_indirect_iterator_tests()
 | 
			
		||||
{
 | 
			
		||||
// For some reason all heck breaks loose in the compiler under these conditions.
 | 
			
		||||
#if !defined(BOOST_MSVC) || !defined(__STL_DEBUG)
 | 
			
		||||
    storage store(1000);
 | 
			
		||||
    std::generate(store.begin(), store.end(), rand);
 | 
			
		||||
    
 | 
			
		||||
    pointer_deque ptr_deque;
 | 
			
		||||
    iterator_set iter_set;
 | 
			
		||||
 | 
			
		||||
    for (storage::iterator p = store.begin(); p != store.end(); ++p)
 | 
			
		||||
    {
 | 
			
		||||
        ptr_deque.push_back(&*p);
 | 
			
		||||
        iter_set.insert(p);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    typedef boost::indirect_iterator_pair_generator<
 | 
			
		||||
        pointer_deque::iterator
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
        , int
 | 
			
		||||
#endif
 | 
			
		||||
    > IndirectDeque;
 | 
			
		||||
 | 
			
		||||
    IndirectDeque::iterator db(ptr_deque.begin());
 | 
			
		||||
    IndirectDeque::iterator de(ptr_deque.end());
 | 
			
		||||
    assert(static_cast<std::size_t>(de - db) == store.size());
 | 
			
		||||
    assert(db + store.size() == de);
 | 
			
		||||
    IndirectDeque::const_iterator dci(db);
 | 
			
		||||
    assert(db == dci);
 | 
			
		||||
    assert(dci == db);
 | 
			
		||||
    assert(dci != de);
 | 
			
		||||
    assert(dci < de);
 | 
			
		||||
    assert(dci <= de);
 | 
			
		||||
    assert(de >= dci);
 | 
			
		||||
    assert(de > dci);
 | 
			
		||||
    dci = de;
 | 
			
		||||
    assert(dci == de);
 | 
			
		||||
 | 
			
		||||
    boost::random_access_iterator_test(db + 1, store.size() - 1, boost::next(store.begin()));
 | 
			
		||||
    
 | 
			
		||||
    *db = 999;
 | 
			
		||||
    assert(store.front() == 999);
 | 
			
		||||
 | 
			
		||||
    typedef boost::indirect_iterator_generator<
 | 
			
		||||
        iterator_set::iterator
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
        , int
 | 
			
		||||
#endif
 | 
			
		||||
        >::type indirect_set_iterator;
 | 
			
		||||
 | 
			
		||||
    typedef boost::indirect_iterator_generator<
 | 
			
		||||
        iterator_set::iterator,
 | 
			
		||||
        const int
 | 
			
		||||
        >::type const_indirect_set_iterator;
 | 
			
		||||
 | 
			
		||||
    indirect_set_iterator sb(iter_set.begin());
 | 
			
		||||
    indirect_set_iterator se(iter_set.end());
 | 
			
		||||
    const_indirect_set_iterator sci(iter_set.begin());
 | 
			
		||||
    assert(sci == sb);
 | 
			
		||||
    assert(sci != se);
 | 
			
		||||
    sci = se;
 | 
			
		||||
    assert(sci == se);
 | 
			
		||||
    
 | 
			
		||||
    *boost::prior(se) = 888;
 | 
			
		||||
    assert(store.back() == 888);
 | 
			
		||||
    assert(std::equal(sb, se, store.begin()));
 | 
			
		||||
 | 
			
		||||
    boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]);
 | 
			
		||||
    assert(std::equal(db, de, store.begin()));
 | 
			
		||||
#endif    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main()
 | 
			
		||||
{
 | 
			
		||||
  dummyT array[] = { dummyT(0), dummyT(1), dummyT(2), 
 | 
			
		||||
                     dummyT(3), dummyT(4), dummyT(5) };
 | 
			
		||||
  const int N = sizeof(array)/sizeof(dummyT);
 | 
			
		||||
 | 
			
		||||
  // sanity check, if this doesn't pass the test is buggy
 | 
			
		||||
  boost::random_access_iterator_test(array,N,array);
 | 
			
		||||
 | 
			
		||||
  // Check that the policy concept checks and the default policy
 | 
			
		||||
  // implementation match up.
 | 
			
		||||
  boost::function_requires< 
 | 
			
		||||
     boost::RandomAccessIteratorPoliciesConcept<
 | 
			
		||||
       boost::default_iterator_policies, int*,
 | 
			
		||||
       boost::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t,
 | 
			
		||||
                      int*, int&>
 | 
			
		||||
      > >();
 | 
			
		||||
 | 
			
		||||
  // Test the iterator_adaptor
 | 
			
		||||
  {
 | 
			
		||||
    my_iterator i(array);
 | 
			
		||||
    boost::random_access_iterator_test(i, N, array);
 | 
			
		||||
    
 | 
			
		||||
    const_my_iterator j(array);
 | 
			
		||||
    boost::random_access_iterator_test(j, N, array);
 | 
			
		||||
    boost::const_nonconst_iterator_test(i, ++j);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Test transform_iterator
 | 
			
		||||
  {
 | 
			
		||||
    int x[N], y[N];
 | 
			
		||||
    for (int k = 0; k < N; ++k)
 | 
			
		||||
      x[k] = k;
 | 
			
		||||
    std::copy(x, x + N, y);
 | 
			
		||||
 | 
			
		||||
    for (int k2 = 0; k2 < N; ++k2)
 | 
			
		||||
      x[k2] = x[k2] * 2;
 | 
			
		||||
 | 
			
		||||
    boost::transform_iterator_generator<mult_functor, int*>::type
 | 
			
		||||
      i(y, mult_functor(2));
 | 
			
		||||
    boost::input_iterator_test(i, x[0], x[1]);
 | 
			
		||||
    boost::input_iterator_test(boost::make_transform_iterator(&y[0], mult_functor(2)), x[0], x[1]);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // Test indirect_iterator_generator
 | 
			
		||||
  {
 | 
			
		||||
    dummyT* ptr[N];
 | 
			
		||||
    for (int k = 0; k < N; ++k)
 | 
			
		||||
      ptr[k] = array + k;
 | 
			
		||||
 | 
			
		||||
    typedef boost::indirect_iterator_generator<dummyT**
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
        , dummyT
 | 
			
		||||
#endif
 | 
			
		||||
      >::type indirect_iterator;
 | 
			
		||||
 | 
			
		||||
    typedef boost::indirect_iterator_generator<dummyT**, const dummyT>::type const_indirect_iterator;
 | 
			
		||||
 | 
			
		||||
    indirect_iterator i(ptr);
 | 
			
		||||
    boost::random_access_iterator_test(i, N, array);
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array);
 | 
			
		||||
#endif
 | 
			
		||||
    
 | 
			
		||||
    // check operator->
 | 
			
		||||
    assert((*i).m_x == i->foo());
 | 
			
		||||
 | 
			
		||||
    const_indirect_iterator j(ptr);
 | 
			
		||||
    boost::random_access_iterator_test(j, N, array);
 | 
			
		||||
 | 
			
		||||
    dummyT*const* const_ptr = ptr;
 | 
			
		||||
    
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array);
 | 
			
		||||
#endif
 | 
			
		||||
    boost::const_nonconst_iterator_test(i, ++j);
 | 
			
		||||
 | 
			
		||||
    more_indirect_iterator_tests();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Test projection_iterator_pair_generator
 | 
			
		||||
  {    
 | 
			
		||||
    typedef std::pair<dummyT,dummyT> Pair;
 | 
			
		||||
    Pair pair_array[N];
 | 
			
		||||
    for (int k = 0; k < N; ++k)
 | 
			
		||||
      pair_array[k].first = array[k];
 | 
			
		||||
 | 
			
		||||
    typedef boost::projection_iterator_pair_generator<select1st_<Pair>,
 | 
			
		||||
      Pair*, const Pair*
 | 
			
		||||
      > Projection;
 | 
			
		||||
    
 | 
			
		||||
    Projection::iterator i(pair_array);
 | 
			
		||||
    boost::random_access_iterator_test(i, N, array);
 | 
			
		||||
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_projection_iterator(pair_array, select1st_<Pair>()), N, array);    
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_projection_iterator< select1st_<Pair> >(pair_array), N, array);    
 | 
			
		||||
 | 
			
		||||
    Projection::const_iterator j(pair_array);
 | 
			
		||||
    boost::random_access_iterator_test(j, N, array);
 | 
			
		||||
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_const_projection_iterator(pair_array, select1st_<Pair>()), N, array);
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_const_projection_iterator<select1st_<Pair> >(pair_array), N, array);
 | 
			
		||||
 | 
			
		||||
    boost::const_nonconst_iterator_test(i, ++j);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Test reverse_iterator_generator
 | 
			
		||||
  {
 | 
			
		||||
    dummyT reversed[N];
 | 
			
		||||
    std::copy(array, array + N, reversed);
 | 
			
		||||
    std::reverse(reversed, reversed + N);
 | 
			
		||||
    
 | 
			
		||||
    typedef boost::reverse_iterator_generator<dummyT*
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
        , dummyT
 | 
			
		||||
#endif
 | 
			
		||||
      >::type reverse_iterator;
 | 
			
		||||
    
 | 
			
		||||
    reverse_iterator i(reversed + N);
 | 
			
		||||
    boost::random_access_iterator_test(i, N, array);
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    typedef boost::reverse_iterator_generator<const dummyT*
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
        , const dummyT
 | 
			
		||||
#endif
 | 
			
		||||
      >::type const_reverse_iterator;
 | 
			
		||||
    
 | 
			
		||||
    const_reverse_iterator j(reversed + N);
 | 
			
		||||
    boost::random_access_iterator_test(j, N, array);
 | 
			
		||||
 | 
			
		||||
    const dummyT* const_reversed = reversed;
 | 
			
		||||
    
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
 | 
			
		||||
#endif
 | 
			
		||||
    
 | 
			
		||||
    boost::const_nonconst_iterator_test(i, ++j);    
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Test reverse_iterator_generator again, with traits fully deducible on all platforms
 | 
			
		||||
  {
 | 
			
		||||
    std::deque<dummyT> reversed_container;
 | 
			
		||||
    std::reverse_copy(array, array + N, std::back_inserter(reversed_container));
 | 
			
		||||
    const std::deque<dummyT>::iterator reversed = reversed_container.begin();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    typedef boost::reverse_iterator_generator<
 | 
			
		||||
        std::deque<dummyT>::iterator>::type reverse_iterator;
 | 
			
		||||
    typedef boost::reverse_iterator_generator<
 | 
			
		||||
        std::deque<dummyT>::const_iterator, const dummyT>::type const_reverse_iterator;
 | 
			
		||||
 | 
			
		||||
    // MSVC/STLport gives an INTERNAL COMPILER ERROR when any computation
 | 
			
		||||
    // (e.g. "reversed + N") is used in the constructor below.
 | 
			
		||||
    const std::deque<dummyT>::iterator finish = reversed_container.end();
 | 
			
		||||
    reverse_iterator i(finish);
 | 
			
		||||
    
 | 
			
		||||
    boost::random_access_iterator_test(i, N, array);
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
 | 
			
		||||
 | 
			
		||||
    const_reverse_iterator j = reverse_iterator(finish);
 | 
			
		||||
    boost::random_access_iterator_test(j, N, array);
 | 
			
		||||
 | 
			
		||||
    const std::deque<dummyT>::const_iterator const_reversed = reversed;
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
 | 
			
		||||
    
 | 
			
		||||
    // Many compilers' builtin deque iterators don't interoperate well, though
 | 
			
		||||
    // STLport fixes that problem.
 | 
			
		||||
#if defined(__SGI_STL_PORT) || !defined(__GNUC__) && !defined(__BORLANDC__) && !defined(BOOST_MSVC)
 | 
			
		||||
    boost::const_nonconst_iterator_test(i, ++j);
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // Test integer_range's iterators
 | 
			
		||||
  {
 | 
			
		||||
    int int_array[] = { 0, 1, 2, 3, 4, 5 };
 | 
			
		||||
    boost::integer_range<int> r(0, 5);
 | 
			
		||||
    boost::random_access_iterator_test(r.begin(), r.size(), int_array);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Test filter iterator
 | 
			
		||||
  {
 | 
			
		||||
    // Using typedefs for filter_gen::type and filter_gen::policies_type
 | 
			
		||||
    // confused Borland terribly.
 | 
			
		||||
    typedef boost::detail::non_bidirectional_category<dummyT*>::type category;
 | 
			
		||||
    
 | 
			
		||||
    typedef ::boost::filter_iterator_generator<one_or_four, dummyT*
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
        , dummyT
 | 
			
		||||
#endif
 | 
			
		||||
        > filter_iter_gen;
 | 
			
		||||
 | 
			
		||||
#ifndef __BORLANDC__
 | 
			
		||||
    typedef filter_iter_gen::type filter_iter;
 | 
			
		||||
#else
 | 
			
		||||
# define filter_iter filter_iter_gen::type // Borland has a problem with the above
 | 
			
		||||
#endif
 | 
			
		||||
    filter_iter i(array, filter_iter::policies_type(one_or_four(), array + N));
 | 
			
		||||
    boost::forward_iterator_test(i, dummyT(1), dummyT(4));
 | 
			
		||||
 | 
			
		||||
    enum { is_forward = boost::is_same<
 | 
			
		||||
           filter_iter::iterator_category,
 | 
			
		||||
           std::forward_iterator_tag>::value };
 | 
			
		||||
    BOOST_STATIC_ASSERT(is_forward);
 | 
			
		||||
 | 
			
		||||
    // On compilers not supporting partial specialization, we can do more type
 | 
			
		||||
    // deduction with deque iterators than with pointers... unless the library
 | 
			
		||||
    // is broken ;-(
 | 
			
		||||
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT)
 | 
			
		||||
    std::deque<dummyT> array2;
 | 
			
		||||
    std::copy(array+0, array+N, std::back_inserter(array2));
 | 
			
		||||
    boost::forward_iterator_test(
 | 
			
		||||
        boost::make_filter_iterator(array2.begin(), array2.end(), one_or_four()),
 | 
			
		||||
        dummyT(1), dummyT(4));
 | 
			
		||||
 | 
			
		||||
    boost::forward_iterator_test(
 | 
			
		||||
        boost::make_filter_iterator<one_or_four>(array2.begin(), array2.end()),
 | 
			
		||||
        dummyT(1), dummyT(4));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined(BOOST_MSVC) // This just freaks MSVC out completely
 | 
			
		||||
    boost::forward_iterator_test(
 | 
			
		||||
        boost::make_filter_iterator<one_or_four>(
 | 
			
		||||
            boost::make_reverse_iterator(array2.end()),
 | 
			
		||||
            boost::make_reverse_iterator(array2.begin())
 | 
			
		||||
            ),
 | 
			
		||||
        dummyT(4), dummyT(1));
 | 
			
		||||
#endif
 | 
			
		||||
    
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
    boost::forward_iterator_test(
 | 
			
		||||
        boost::make_filter_iterator(array+0, array+N, one_or_four()),
 | 
			
		||||
        dummyT(1), dummyT(4));
 | 
			
		||||
 | 
			
		||||
    boost::forward_iterator_test(
 | 
			
		||||
        boost::make_filter_iterator<one_or_four>(array, array + N),
 | 
			
		||||
        dummyT(1), dummyT(4));
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // check operator-> with a forward iterator
 | 
			
		||||
  {
 | 
			
		||||
    boost::forward_iterator_archetype<dummyT> forward_iter;
 | 
			
		||||
    typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
 | 
			
		||||
      boost::default_iterator_policies,
 | 
			
		||||
      dummyT, const dummyT&, const dummyT*, 
 | 
			
		||||
      std::forward_iterator_tag, std::ptrdiff_t> adaptor_type;
 | 
			
		||||
    adaptor_type i(forward_iter);
 | 
			
		||||
    if (0) // don't do this, just make sure it compiles
 | 
			
		||||
      assert((*i).m_x == i->foo());      
 | 
			
		||||
  }
 | 
			
		||||
  // check operator-> with an input iterator
 | 
			
		||||
  {
 | 
			
		||||
    boost::input_iterator_archetype<dummyT> input_iter;
 | 
			
		||||
    typedef boost::iterator_adaptor<boost::input_iterator_archetype<dummyT>,
 | 
			
		||||
      boost::default_iterator_policies,
 | 
			
		||||
      dummyT, const dummyT&, const dummyT*, 
 | 
			
		||||
      std::input_iterator_tag, std::ptrdiff_t> adaptor_type;
 | 
			
		||||
    adaptor_type i(input_iter);
 | 
			
		||||
    if (0) // don't do this, just make sure it compiles
 | 
			
		||||
      assert((*i).m_x == i->foo());      
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::cout << "test successful " << std::endl;
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,210 +0,0 @@
 | 
			
		||||
//  (C) Copyright David Abrahams 2001. Permission to copy, use, modify,
 | 
			
		||||
//  sell and distribute this software is granted provided this
 | 
			
		||||
//  copyright notice appears in all copies. This software is provided
 | 
			
		||||
//  "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
//  to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  04 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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										331
									
								
								reverse_iterator.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										331
									
								
								reverse_iterator.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,331 @@
 | 
			
		||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
 | 
			
		||||
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
    <meta name="generator" content="HTML Tidy, see www.w3.org">
 | 
			
		||||
    <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
 | 
			
		||||
    <meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
    <meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
 | 
			
		||||
    <title>Reverse Iterator Adaptor Documentation</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
    <img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
 | 
			
		||||
    "center" width="277" height="86"> 
 | 
			
		||||
 | 
			
		||||
    <h1>Reverse Iterator Adaptor</h1>
 | 
			
		||||
    Defined in header <a href=
 | 
			
		||||
    "../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a> 
 | 
			
		||||
 | 
			
		||||
    <p>The reverse iterator adaptor flips the direction of a base iterator's
 | 
			
		||||
    motion. Invoking <tt>operator++()</tt> moves the base iterator backward and
 | 
			
		||||
    invoking <tt>operator--()</tt> moves the base iterator forward. The Boost
 | 
			
		||||
    reverse iterator adaptor is better to use than the
 | 
			
		||||
    <tt>std::reverse_iterator</tt> class in situations where pairs of
 | 
			
		||||
    mutable/constant iterators are needed (e.g., in containers) because
 | 
			
		||||
    comparisons and conversions between the mutable and const versions are
 | 
			
		||||
    implemented correctly.
 | 
			
		||||
 | 
			
		||||
    <h2>Synopsis</h2>
 | 
			
		||||
<pre>
 | 
			
		||||
namespace boost {
 | 
			
		||||
  template <class <a href=
 | 
			
		||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>,
 | 
			
		||||
            class Value, class Reference, class Pointer, class Category, class Distance>
 | 
			
		||||
  struct reverse_iterator_generator;
 | 
			
		||||
  
 | 
			
		||||
  template <class <a href=
 | 
			
		||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>>
 | 
			
		||||
  typename reverse_iterator_generator<BidirectionalIterator>::type
 | 
			
		||||
  make_reverse_iterator(BidirectionalIterator base)  
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
    <hr>
 | 
			
		||||
 | 
			
		||||
    <h2><a name="reverse_iterator_generator">The Reverse Iterator Type
 | 
			
		||||
    Generator</a></h2>
 | 
			
		||||
    The <tt>reverse_iterator_generator</tt> template is a <a href=
 | 
			
		||||
    "../../more/generic_programming.html#type_generator">generator</a> of
 | 
			
		||||
    reverse iterator types. The main template parameter for this class is the
 | 
			
		||||
    base <tt>BidirectionalIterator</tt> type that is being adapted. In most
 | 
			
		||||
    cases the associated types of the base iterator can be deduced using
 | 
			
		||||
    <tt>std::iterator_traits</tt>, but in some situations the user may want to
 | 
			
		||||
    override these types, so there are also template parameters for the base
 | 
			
		||||
    iterator's associated types. 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
template <class <a href=
 | 
			
		||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>,
 | 
			
		||||
          class Value, class Reference, class Pointer, class Category, class Distance>
 | 
			
		||||
class reverse_iterator_generator
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  typedef <tt><a href=
 | 
			
		||||
"./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> type; // the resulting reverse iterator type 
 | 
			
		||||
};
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
 | 
			
		||||
    <h3>Example</h3>
 | 
			
		||||
    In this example we sort a sequence of letters and then output the sequence
 | 
			
		||||
    in descending order using reverse iterators. 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <boost/iterator_adaptors.hpp>
 | 
			
		||||
 | 
			
		||||
int main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  char letters[] = "hello world!";
 | 
			
		||||
  const int N = sizeof(letters)/sizeof(char) - 1;
 | 
			
		||||
  std::cout << "original sequence of letters:\t"
 | 
			
		||||
      << letters << std::endl;
 | 
			
		||||
 | 
			
		||||
  std::sort(letters, letters + N);
 | 
			
		||||
 | 
			
		||||
  // Use reverse_iterator_generator to print a sequence
 | 
			
		||||
  // of letters in reverse order.
 | 
			
		||||
  
 | 
			
		||||
  boost::reverse_iterator_generator<char*>::type
 | 
			
		||||
    reverse_letters_first(letters + N),
 | 
			
		||||
    reverse_letters_last(letters);
 | 
			
		||||
 | 
			
		||||
  std::cout << "letters in descending order:\t";
 | 
			
		||||
  std::copy(reverse_letters_first, reverse_letters_last,
 | 
			
		||||
      std::ostream_iterator<char>(std::cout));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // to be continued...
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
    The output is: 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
original sequence of letters: hello world!
 | 
			
		||||
letters in descending order:  wroolllhed! 
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
 | 
			
		||||
    <h3>Template Parameters</h3>
 | 
			
		||||
 | 
			
		||||
    <table border>
 | 
			
		||||
      <tr>
 | 
			
		||||
        <th>Parameter
 | 
			
		||||
 | 
			
		||||
        <th>Description
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt><a href=
 | 
			
		||||
        "http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a></tt>
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        <td>The iterator type being wrapped.
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Value</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The value-type of the base iterator and the resulting reverse
 | 
			
		||||
        iterator.<br>
 | 
			
		||||
         <b>Default:</b><tt>std::iterator_traits<BidirectionalIterator>::value_type</tt>
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Reference</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The <tt>reference</tt> type of the resulting iterator, and in
 | 
			
		||||
        particular, the result type of <tt>operator*()</tt>.<br>
 | 
			
		||||
         <b>Default:</b> If <tt>Value</tt> is supplied, <tt>Value&</tt> is
 | 
			
		||||
        used. Otherwise
 | 
			
		||||
        <tt>std::iterator_traits<BidirectionalIterator>::reference</tt>
 | 
			
		||||
        is used.
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Pointer</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The <tt>pointer</tt> type of the resulting iterator, and in
 | 
			
		||||
        particular, the result type of <tt>operator->()</tt>.<br>
 | 
			
		||||
         <b>Default:</b> If <tt>Value</tt> was supplied, then <tt>Value*</tt>,
 | 
			
		||||
        otherwise
 | 
			
		||||
        <tt>std::iterator_traits<BidirectionalIterator>::pointer</tt>.
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Category</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
 | 
			
		||||
         <b>Default:</b>
 | 
			
		||||
        <tt>std::iterator_traits<BidirectionalIterator>::iterator_category</tt>
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Distance</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The <tt>difference_type</tt> for the resulting iterator.<br>
 | 
			
		||||
         <b>Default:</b>
 | 
			
		||||
        <tt>std::iterator_traits<BidirectionalIterator&gt::difference_type</tt>
 | 
			
		||||
        
 | 
			
		||||
    </table>
 | 
			
		||||
 | 
			
		||||
    <h3>Concept Model</h3>
 | 
			
		||||
    The indirect iterator will model whichever <a href=
 | 
			
		||||
    "http://www.sgi.com/tech/stl/Iterators.html">standard iterator concept
 | 
			
		||||
    category</a> is modeled by the base iterator. Thus, if the base iterator is
 | 
			
		||||
    a model of <a href=
 | 
			
		||||
    "http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
 | 
			
		||||
    Iterator</a> then so is the resulting indirect iterator. If the base
 | 
			
		||||
    iterator models a more restrictive concept, the resulting indirect iterator
 | 
			
		||||
    will model the same concept. The base iterator must be at least a <a href=
 | 
			
		||||
    "http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional
 | 
			
		||||
    Iterator</a> 
 | 
			
		||||
 | 
			
		||||
    <h3>Members</h3>
 | 
			
		||||
    The reverse iterator type implements the member functions and operators
 | 
			
		||||
    required of the <a href=
 | 
			
		||||
    "http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
 | 
			
		||||
    Iterator</a> concept. In addition it has the following constructor: 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
reverse_iterator_generator::type(const BidirectionalIterator& it)
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <br>
 | 
			
		||||
     <br>
 | 
			
		||||
     
 | 
			
		||||
    <hr>
 | 
			
		||||
 | 
			
		||||
    <p>
 | 
			
		||||
 | 
			
		||||
    <h2><a name="make_reverse_iterator">The Reverse Iterator Object
 | 
			
		||||
    Generator</a></h2>
 | 
			
		||||
    The <tt>make_reverse_iterator()</tt> function provides a more convenient
 | 
			
		||||
    way to create reverse iterator objects. The function saves the user the
 | 
			
		||||
    trouble of explicitly writing out the iterator types. 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
template <class BidirectionalIterator>
 | 
			
		||||
typename reverse_iterator_generator<BidirectionalIterator>::type
 | 
			
		||||
make_reverse_iterator(BidirectionalIterator base);
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
 | 
			
		||||
    <h3>Example</h3>
 | 
			
		||||
    In this part of the example we use <tt>make_reverse_iterator()</tt> to
 | 
			
		||||
    print the sequence of letters in reverse-reverse order, which is the
 | 
			
		||||
    original order. 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
  // continuing from the previous example...
 | 
			
		||||
 | 
			
		||||
  std::cout << "letters in ascending order:\t";
 | 
			
		||||
  std::copy(boost::make_reverse_iterator(reverse_letters_last),
 | 
			
		||||
      boost::make_reverse_iterator(reverse_letters_first),
 | 
			
		||||
      std::ostream_iterator<char>(std::cout));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
    The output is: 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
letters in ascending order:  !dehllloorw
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
    <hr>
 | 
			
		||||
 | 
			
		||||
    <h2><a name="interactions">Constant/Mutable Iterator Interactions</a></h2>
 | 
			
		||||
 | 
			
		||||
    <p>One failing of the standard <tt><a
 | 
			
		||||
    href="http://www.sgi.com/tech/stl/ReverseIterator.html">reverse_iterator</a></tt>
 | 
			
		||||
    adaptor is that it doesn't properly support interactions between adapted
 | 
			
		||||
    <tt>const</tt> and non-<tt>const</tt> iterators. For example:
 | 
			
		||||
<blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
template <class T> void convert(T x) {}
 | 
			
		||||
 | 
			
		||||
// Test interactions of a matched pair of random access iterators
 | 
			
		||||
template <class Iterator, class ConstIterator>
 | 
			
		||||
void test_interactions(Iterator i, ConstIterator ci)
 | 
			
		||||
{
 | 
			
		||||
  bool eq = i == ci;               // comparisons
 | 
			
		||||
  bool ne = i != ci;            
 | 
			
		||||
  bool lt = i < ci;
 | 
			
		||||
  bool le = i <= ci;
 | 
			
		||||
  bool gt = i > ci;
 | 
			
		||||
  bool ge = i >= ci;
 | 
			
		||||
  std::size_t distance = i - ci;   // difference
 | 
			
		||||
  ci = i;                          // assignment
 | 
			
		||||
  ConstIterator ci2(i);            // construction
 | 
			
		||||
  convert<ConstIterator>(i);       // implicit conversion
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void f()
 | 
			
		||||
{
 | 
			
		||||
  typedef std::vector<int> vec;
 | 
			
		||||
  vec v;
 | 
			
		||||
  const vec& cv;
 | 
			
		||||
 | 
			
		||||
  test_interactions(v.begin(), cv.begin());   // <font color="#007F00">OK</font>
 | 
			
		||||
  test_interactions(v.rbegin(), cv.rbegin()); // <font color="#FF0000">ERRORS ON EVERY TEST!!</font>
 | 
			
		||||
</pre>
 | 
			
		||||
</blockquote>
 | 
			
		||||
Reverse iterators created with <tt>boost::reverse_iterator_generator</tt> don't have this problem, though:
 | 
			
		||||
<blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
  typedef boost::reverse_iterator_generator<vec::iterator>::type ri;
 | 
			
		||||
  typedef boost::reverse_iterator_generator<vec::const_iterator>::type cri;
 | 
			
		||||
  test_interactions(ri(v.begin()), cri(cv.begin()));   // <font color="#007F00">OK!!</font>
 | 
			
		||||
</pre>
 | 
			
		||||
</blockquote>
 | 
			
		||||
Or, more simply,
 | 
			
		||||
<blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
  test_interactions(
 | 
			
		||||
    boost::make_reverse_iterator(v.begin()), 
 | 
			
		||||
    boost::make_reverse_iterator(cv.begin()));   // <font color="#007F00">OK!!</font>
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
</blockquote>
 | 
			
		||||
 | 
			
		||||
<p>If you are wondering why there is no
 | 
			
		||||
<tt>reverse_iterator_pair_generator</tt> in the manner of <tt><a
 | 
			
		||||
href="projection_iterator.htm#projection_iterator_pair_generator">projection_iterator_pair_generator</a></tt>,
 | 
			
		||||
the answer is simple: we tried it, but found that in practice it took
 | 
			
		||||
<i>more</i> typing to use <tt>reverse_iterator_pair_generator</tt> than to
 | 
			
		||||
simply use <tt>reverse_iterator_generator</tt> twice!<br><br>
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    <p>Revised 
 | 
			
		||||
    <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->26 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14386" -->
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <p>© 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" without express or
 | 
			
		||||
    implied warranty, and with no claim as to its suitability for any purpose. 
 | 
			
		||||
    <!--  LocalWords:  html charset alt gif hpp BidirectionalIterator const namespace struct
 | 
			
		||||
         -->
 | 
			
		||||
     
 | 
			
		||||
    <!--  LocalWords:  ConstPointer ConstReference typename iostream int abcdefg
 | 
			
		||||
         -->
 | 
			
		||||
     <!--  LocalWords:  sizeof  PairGen pre Siek wroolllhed dehllloorw
 | 
			
		||||
         -->
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user