/*************************************************************************** * * alg_test.h - common definitions for algorithms tests * * $Id: alg_test.h 550991 2007-06-26 23:58:07Z sebor $ * *************************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * * Copyright 1994-2005 Rogue Wave Software. * **************************************************************************/ #ifndef RW_ALG_TEST_H_INCLUDED #define RW_ALG_TEST_H_INCLUDED #include // for iterator #include // generate a unique sequential number starting from 0 _TEST_EXPORT int gen_seq (); // generate numbers in the sequence 0, 0, 1, 1, 2, 2, 3, 3, etc... _TEST_EXPORT int gen_seq_2lists (); // generate a sequence of subsequences (i.e., 0, 1, 2, 3, 4, 0, 1, 2, etc...) _TEST_EXPORT int gen_subseq (); // wrapper around a (possibly) extern "C" int rand() // extern "C++" _TEST_EXPORT int gen_rnd (); // computes an integral log2 _TEST_EXPORT unsigned ilog2 (_RWSTD_SIZE_T); // computes an integral log10 _TEST_EXPORT unsigned ilog10 (_RWSTD_SIZE_T); template inline bool is_sorted (InputIterator first, InputIterator last, Predicate pred) { if (first == last) return true; for (InputIterator prev (first); ++first != last; prev = first) { if (pred (*first, *prev)) return false; } return true; } // returns true iff a sequence of (not necessarily unique) values // is sorted in an ascending order template inline bool is_sorted_lt (InputIterator first, InputIterator last) { if (first == last) return true; for (InputIterator prev (first); ++first != last; prev = first) { if (*first < *prev) return false; } return true; } // returns true iff a sequence of (not necessarily unique) values // is sorted in a descending order template inline bool is_sorted_gt (InputIterator first, InputIterator last) { if (first == last) return true; for (InputIterator prev (first); ++first != last; prev = first) { if (*prev < *first) return false; } return true; } /**************************************************************************/ // type used to exercise that algorithms do not apply operators // to function objects the latter are not required to define struct conv_to_bool { static conv_to_bool make (bool val) { return conv_to_bool (val); } #if !defined (_MSC_VER) || _MSC_VER > 1300 // unique pointer not compatible with any other typedef bool conv_to_bool::*UniquePtr; // strictly convertible to a Boolean value testable // in the controlling expression of the if statement // as required in 25, p7 operator UniquePtr () const { return val_ ? &conv_to_bool::val_ : UniquePtr (0); } #else typedef const void* UniquePtr; operator UniquePtr () const { return val_ ? &val_ : UniquePtr (0); } #endif private: // not (publicly) Default-Constructible conv_to_bool (bool val): val_ (val) { } void operator= (conv_to_bool); // not Assignable void operator!() const; // not defined bool val_; }; // not defined void operator&& (const conv_to_bool&, bool); void operator&& (bool, const conv_to_bool&); void operator|| (const conv_to_bool&, bool); void operator|| (bool, const conv_to_bool&); // element-type prototypes to exercise container requirements // meets requirements listed at 25, p7 template struct predicate { conv_to_bool operator() (const T &a) const { _RWSTD_UNUSED (a); return conv_to_bool::make (true); } }; // meets requirements listed at 25, p8 template struct binary_predicate { conv_to_bool operator() (const T &a, const T &b) const { _RWSTD_UNUSED (a); _RWSTD_UNUSED (b); return conv_to_bool::make (true); } }; // meets requirements listed at 25.2.3, p2 template struct func { typedef T argument_type; typedef argument_type& reference; reference operator() (const argument_type&) const { return _RWSTD_REINTERPRET_CAST (reference, _RWSTD_CONST_CAST (func*, this)->dummy); } private: char dummy; }; // meets requirements listed at 25.2.3, p2 template struct binary_func { typedef T argument_type; typedef argument_type& reference; reference operator() (const argument_type&, const argument_type&) const { return _RWSTD_REINTERPRET_CAST (reference, _RWSTD_CONST_CAST (binary_func*, this)->dummy); } private: char dummy; }; // a base-class to extend the requirements classes from enum { no_ctor = 0, def_ctor = 1, cpy_ctor = 2 }; template struct base; template<> struct base { private: // struct s added to prevent gcc warning: base has a private // constructor and no friends struct s { }; friend struct s; base (); base (const base&); void operator= (base&); }; template<> struct base { base () : unused (0) { } private: void operator= (base&); base (const base&); // unused member prevents bogus HP aCC warnings (see Onyx #23561) int unused; }; template<> struct base { // explicitly specifying redundant template parameters to work // around a SunPro 5.2 bug (see Onyx #24260) base (const base &rhs): unused (rhs.unused) { } private: base (); void operator= (base&); // unused member prevents bogus HP aCC warnings (see Onyx #23561) int unused; }; template<> struct base<(def_ctor | cpy_ctor)> { base (): unused (0) { } // explicitly specifying redundant template parameters to work // around a SunPro 5.2 bug (see Onyx #24260) base (const base<(def_ctor | cpy_ctor)> &rhs): unused (rhs.unused) { } private: void operator= (base&); // unused member prevents bogus HP aCC warnings (see Onyx #23561) int unused; }; template struct eq_comp: T { }; template inline bool operator== (const eq_comp&, const eq_comp&) { return true; } template struct lt_comp: T { }; template inline bool operator< (const lt_comp&, const lt_comp&) { return true; } // assignment template struct assign : T { assign& operator= (const assign& rhs) { unused = rhs.unused; return *this; } private: // unused member prevents bogus HP aCC warnings (see Onyx #23561) int unused; }; // conversion structs // struct split into 2 to eliminate the following g++ 2.95.2 warning: // warning: choosing `convert::operator U&()' over // `convert::operator const U&() const' template struct cvt : T { operator U& () { return _RWSTD_REINTERPRET_CAST (U&, *this); } }; template struct const_cvt : T { operator const U& () const { return _RWSTD_REINTERPRET_CAST (const U&, *this); } }; /**************************************************************************/ // Size template argument to fill_n(), generate_n(), and search_n() template struct Size { // dummy argument provided to prevent Size from being constructible // by conversion from IntegralT Size (IntegralT val, int /* dummy */ ) : val_ (val) { /* empty */ } // Size must be convertible to an integral type operator IntegralT () const { return val_; } private: void operator= (const Size&); // not Assignable IntegralT val_; }; /**************************************************************************/ #ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC struct DummyBase { }; # define ITER_BASE(ign1, ign2, ign3, ign4, ign5) DummyBase #else // if defined (_RWSTD_NO_CLASS_PARTIAL_SPEC) // when partial specialization isn't supported # define ITER_BASE(Cat, T, Dist, Ptr, Ref) \ std::iterator #endif // _RWSTD_NO_CLASS_PARTIAL_SPEC // satisfies the requirements in 24.1.1 [lib.input.iterators] template struct InputIter: ITER_BASE (std::input_iterator_tag, T, int, T*, T&) { typedef T value_type; typedef value_type* pointer; typedef value_type& reference; typedef _RWSTD_PTRDIFF_T difference_type; typedef std::input_iterator_tag iterator_category; // body shared by all copies of the same InputIter specialization // to detect algorithms that pass through the same interator more // than once (disallowed by 24.1.1, p3) struct Shared { const value_type *cur_; const value_type *beg_; const value_type *end_; int ref_; Shared (const value_type *cur, const value_type *beg, const value_type *end) : cur_ (cur), beg_ (beg), end_ (end), ref_ (1) { RW_ASSERT (beg_ <= cur_ && cur_ <= end_); } ~Shared () { cur_ = beg_ = end_ = 0; ref_ = -1; } private: Shared (const Shared&); // not defined void operator= (const Shared&); // not defined }; // InputIterators are not default constructible InputIter (const value_type* /* current */, const value_type* /* begin */, const value_type* /* end */); InputIter (const InputIter&); ~InputIter (); InputIter& operator= (const InputIter&); bool operator== (const InputIter&) const; bool operator!= (const InputIter &rhs) const { return !(*this == rhs); } // returning const-reference rather than a value in order // not to impose the CopyConstructible requirement on T // and to disallow constructs like *InputIter() = T() const value_type& operator* () const { RW_ASSERT (*this == *this); // assert *this is valid RW_ASSERT (cur_ < ptr_->end_); // assert *this is dereferenceable return *cur_; } _RWSTD_OPERATOR_ARROW (const value_type* operator-> () const); InputIter& operator++ () { RW_ASSERT (*this == *this); // assert *this is valid RW_ASSERT (cur_ < ptr_->end_); // assert *this is not past the end ptr_->cur_ = ++cur_; return *this; } InputIter operator++ (int) { return ++*this; } // private: Shared *ptr_; const value_type *cur_; // past-the-end }; // "large" member functions outlined to prevent gcc -Winline warnings template InputIter:: InputIter (const value_type *cur, const value_type *beg, const value_type *end) : ptr_ (new Shared (cur, beg, end)), cur_ (cur) { // empty } template InputIter:: InputIter (const InputIter &rhs) : ptr_ (rhs.ptr_), cur_ (rhs.cur_) { RW_ASSERT (0 != ptr_); ++ptr_->ref_; } template InputIter:: ~InputIter () { RW_ASSERT (0 != ptr_); if (0 == --ptr_->ref_) // decrement the reference count delete ptr_; ptr_ = 0; cur_ = 0; } template InputIter& InputIter:: operator= (const InputIter &rhs) { RW_ASSERT (rhs == rhs); // assert `rhs' is valid RW_ASSERT (0 != ptr_); if (0 == --ptr_->ref_) delete ptr_; ptr_ = rhs.ptr_; RW_ASSERT (0 != ptr_); ++ptr_->ref_; cur_ = rhs.cur_; return *this; } template bool InputIter:: operator== (const InputIter &rhs) const { // assert that both arguments are in the domain of operator==() // i.e., that no copy of *this or `rhs' has been incremented // and that no copy passed through this value of the iterator RW_ASSERT (0 != ptr_); RW_ASSERT (cur_ == ptr_->cur_); RW_ASSERT (0 != rhs.ptr_); RW_ASSERT (rhs.cur_ == rhs.ptr_->cur_); return cur_ == rhs.cur_; } /**************************************************************************/ // satisfies the requirements in 24.1.2 [lib.output.iterators] template struct OutputIter: ITER_BASE (std::output_iterator_tag, T, int, T*, T&) { typedef T value_type; typedef value_type* pointer; typedef value_type& reference; typedef _RWSTD_PTRDIFF_T difference_type; typedef std::output_iterator_tag iterator_category; // body shared by all copies of the same OutputIter specialization // to detect algorithms that pass through the same interator more // than once (disallowed by 24.1.2, p2) struct Shared { pointer cur_; pointer assign_; const value_type *begin_; const value_type *end_; int ref_; Shared (pointer cur, const value_type *end) : cur_ (cur), assign_ (cur), begin_ (cur), end_ (end), ref_ (1) { } ~Shared () { begin_ = end_ = cur_ = assign_ = 0; ref_ = -1; } private: Shared (const Shared&); // not defined void operator= (const Shared&); // not defined }; // class whose objects are returned from OutputIter::operator* // to detect multiple assignments (disallowed by 24.1.2, p2) class Proxy { friend struct OutputIter; Shared* const ptr_; Proxy (Shared *ptr): ptr_ (ptr) { } public: void operator= (const value_type &rhs) { RW_ASSERT (0 != ptr_); // verify that the iterator is in the valid range RW_ASSERT (ptr_->cur_ >= ptr_->begin_ && ptr_->cur_ <= ptr_->end_); // verify that the assignment point is the same as the current // position `cur' within the sequence or immediately before it // (in order to allow the expression: *it++ = val) RW_ASSERT ( ptr_->assign_ == ptr_->cur_ || ptr_->assign_ + 1 == ptr_->cur_); // assign and increment the assignment point *ptr_->assign_++ = rhs; } }; // OutputIterators are not default constructible OutputIter (pointer cur, const value_type *, const value_type *end) : ptr_ (new Shared (cur, end)), cur_ (cur) { } OutputIter (const OutputIter &rhs) : ptr_ (rhs.ptr_), cur_ (rhs.cur_) { ++ptr_->ref_; // increment the reference count } ~OutputIter (); OutputIter& operator= (const OutputIter&); void operator= (const value_type &rhs) const { **this = rhs; } // return a proxy in order to detect multiple assignments // through the iterator (disallowed by 24.1.2, p2)) Proxy operator* () const { RW_ASSERT (0 != ptr_); RW_ASSERT (ptr_->assign_ && ptr_->assign_ != ptr_->end_); return Proxy (ptr_); } _RWSTD_OPERATOR_ARROW (pointer operator-> () const); OutputIter& operator++ () { RW_ASSERT (cur_ == ptr_->cur_); RW_ASSERT (ptr_->cur_ >= ptr_->begin_ && ptr_->cur_ < ptr_->end_); cur_ = ++ptr_->cur_; return *this; } // returning a const value rather than a modifiable value // in order to verify the requirement in row 5 of Table 73 const OutputIter operator++ (int) { OutputIter tmp (*this); return ++*this, tmp; } // private: Shared *ptr_; pointer cur_; }; // "large" member functions outlined to prevent gcc -Winline warnings template OutputIter:: ~OutputIter () { RW_ASSERT (0 != ptr_); if (0 == --ptr_->ref_) // decrement the reference count delete ptr_; ptr_ = 0; cur_ = 0; } template OutputIter& OutputIter:: operator= (const OutputIter &rhs) { RW_ASSERT (0 != ptr_); if (0 == --ptr_->ref_) delete ptr_; ptr_ = rhs.ptr_; ++ptr_->ref_; cur_ = rhs.cur_; return *this; } /**************************************************************************/ // satisfies the requirements in 24.1.3 [lib.forward.iterators] template struct FwdIter: ITER_BASE (std::forward_iterator_tag, T, int, T*, T&) { typedef T value_type; typedef value_type* pointer; typedef value_type& reference; typedef _RWSTD_PTRDIFF_T difference_type; typedef std::forward_iterator_tag iterator_category; FwdIter (): cur_ (0), end_ (0) { } FwdIter (pointer cur, const value_type *, const value_type *end) : cur_ (cur), end_ (end) { } FwdIter (const FwdIter &rhs) : cur_ (rhs.cur_), end_ (rhs.end_) { } ~FwdIter () { end_ = cur_ = 0; } FwdIter& operator= (const FwdIter &rhs) { cur_ = rhs.cur_; end_ = rhs.end_; return *this; } bool operator== (const FwdIter &rhs) const { RW_ASSERT (cur_ != 0); return cur_ == rhs.cur_; } bool operator!= (const FwdIter &rhs) const { return !(*this == rhs); } reference operator* () const { RW_ASSERT (cur_ != 0 && cur_ != end_); return *cur_; } _RWSTD_OPERATOR_ARROW (pointer operator-> () const); FwdIter& operator++ () { RW_ASSERT (cur_ != 0 && cur_ != end_); return ++cur_, *this; } FwdIter operator++ (int) { FwdIter tmp (*this); return ++*this, tmp; } // private: pointer cur_; // pointer to current element const value_type *end_; // past-the-end }; template struct ConstFwdIter: FwdIter { typedef T value_type; typedef FwdIter Base; ConstFwdIter (): Base () { } ConstFwdIter (const value_type *cur, const value_type *begin, const value_type *end) : Base (cur, begin, end) { } const value_type& operator* () const { return Base::operator* (); } _RWSTD_OPERATOR_ARROW (const value_type* operator-> () const); }; /**************************************************************************/ // satisfies the requirements in 24.1.4 [lib.bidirectional.iterators] template struct BidirIter: ITER_BASE (std::bidirectional_iterator_tag, T, int, T*, T&) { typedef T value_type; typedef value_type* pointer; typedef value_type& reference; typedef _RWSTD_PTRDIFF_T difference_type; typedef std::bidirectional_iterator_tag iterator_category; BidirIter (): cur_ (0), begin_ (0), end_ (0) { } BidirIter (pointer cur, const value_type *begin, const value_type *end) : cur_ (cur), begin_ (begin), end_ (end) { } BidirIter (const BidirIter &rhs) : cur_ (rhs.cur_), begin_ (rhs.begin_), end_ (rhs.end_) { } ~BidirIter () { begin_ = end_ = cur_ = 0; } BidirIter& operator= (const BidirIter &rhs) { cur_ = rhs.cur_; end_ = rhs.end_; return *this; } bool operator== (const BidirIter &rhs) const { RW_ASSERT (cur_ != 0 && rhs.cur_ != 0); return cur_ == rhs.cur_; } bool operator!= (const BidirIter &rhs) const { return !(*this == rhs); } reference operator* () const { RW_ASSERT (cur_ != 0 && cur_ != end_); return *cur_; } _RWSTD_OPERATOR_ARROW (pointer operator-> () const); BidirIter& operator++ () { RW_ASSERT (cur_ != 0 && cur_ != end_); return ++cur_, *this; } BidirIter operator++ (int) { BidirIter tmp (*this); return ++*this, tmp; } BidirIter& operator-- () { RW_ASSERT (cur_ != 0 && cur_ != begin_); return --cur_, *this; } BidirIter operator-- (int) { BidirIter tmp (*this); return --*this, tmp; } // private: pointer cur_; // pointer to current element const value_type *begin_; // first in range const value_type *end_; // past-the-end }; template struct ConstBidirIter: BidirIter { typedef T value_type; typedef BidirIter Base; ConstBidirIter (): Base () { } ConstBidirIter (const value_type *cur, const value_type *begin, const value_type *end) : Base (cur, begin, end) { } const value_type& operator* () const { return Base::operator* (); } _RWSTD_OPERATOR_ARROW (const value_type* operator-> () const); }; /**************************************************************************/ // satisfies the requirements in 24.1.5 [lib.random.access.iterators] template struct RandomAccessIter : ITER_BASE (std::random_access_iterator_tag, T, int, T*, T&) { typedef T value_type; typedef value_type* pointer; typedef value_type& reference; typedef _RWSTD_PTRDIFF_T difference_type; typedef std::random_access_iterator_tag iterator_category; RandomAccessIter (): cur_ (0), begin_ (0), end_ (0) { } RandomAccessIter (pointer cur, const value_type *begin, const value_type *end) : cur_ (cur), begin_ (begin), end_ (end) { } RandomAccessIter (const RandomAccessIter &rhs) : cur_ (rhs.cur_), begin_ (rhs.begin_), end_ (rhs.end_) { } ~RandomAccessIter () { begin_ = end_ = cur_ = 0; } RandomAccessIter& operator= (const RandomAccessIter &rhs) { cur_ = rhs.cur_; begin_ = rhs.begin_; end_ = rhs.end_; return *this; } reference operator* () const { RW_ASSERT (cur_ != 0 && cur_ != end_); return *cur_; } _RWSTD_OPERATOR_ARROW (pointer operator-> () const); RandomAccessIter& operator++ () { RW_ASSERT (cur_ != 0 && cur_ != end_); return ++cur_, *this; } RandomAccessIter operator++ (int) { RandomAccessIter tmp (*this); return ++*this, tmp; } RandomAccessIter& operator-- () { RW_ASSERT (cur_ != 0 && cur_ != begin_); return --cur_, *this; } RandomAccessIter operator-- (int) { RandomAccessIter tmp (*this); return --*this, tmp; } RandomAccessIter& operator+= (difference_type n) { RW_ASSERT ( cur_ != 0 && (!end_ || cur_ + n <= end_) && (!begin_ || cur_ + n >= begin_)); return cur_ += n, *this; } RandomAccessIter& operator-= (difference_type n) { return *this += -n; } RandomAccessIter operator+ (difference_type n) const { return RandomAccessIter (*this) += n; } RandomAccessIter operator- (difference_type n) const { return RandomAccessIter (*this) -= n; } difference_type operator- (const RandomAccessIter &rhs) const { RW_ASSERT (cur_ != 0 && rhs.cur_ != 0); return cur_ - rhs.cur_; } bool operator== (const RandomAccessIter &rhs) const { RW_ASSERT (cur_ != 0 && rhs.cur_ != 0); return cur_ == rhs.cur_; } bool operator!= (const RandomAccessIter &rhs) const { return !(*this == rhs); } bool operator< (const RandomAccessIter &rhs) const { RW_ASSERT (cur_ != 0 && rhs.cur_ != 0); return cur_ < rhs.cur_; }; bool operator> (const RandomAccessIter &rhs) const { return rhs < *this; } bool operator<= (const RandomAccessIter &rhs) const { return !(rhs < *this); } bool operator>= (const RandomAccessIter &rhs) const { return !(*this < rhs); } reference operator[] (difference_type inx) const { RW_ASSERT ( cur_ != 0 && (!end_ || cur_ + inx < end_) && !(begin_ || cur_ + inx >= begin_)); return cur_ [inx]; } // private: pointer cur_; // pointer to current element const value_type *begin_; // first in range const value_type *end_; // past-the-end }; /**************************************************************************/ template struct ConstRandomAccessIter: RandomAccessIter { typedef T value_type; typedef RandomAccessIter Base; typedef typename Base::difference_type difference_type; ConstRandomAccessIter (): Base () { } ConstRandomAccessIter (const value_type *cur, const value_type *begin, const value_type *end) : Base (cur, begin, end) { } const value_type& operator* () const { return Base::operator* (); } _RWSTD_OPERATOR_ARROW (const value_type* operator-> () const); const value_type& operator[] (difference_type inx) const { return Base::operator[] (inx); } }; /**************************************************************************/ template inline T* make_iter (T *cur, const T*, const T*, T*) { return cur; } template inline T* copy_iter (T *ptr, const T*) { return ptr; } // dummy function argument provided to help broken compilers (PR #29835) template inline InputIter make_iter (const T *cur, const T *begin, const T *end, const InputIter&) { return InputIter(cur, begin, end); } template inline InputIter copy_iter (const InputIter &it, const T*) { return InputIter(it.cur_, it.ptr_->beg_, it.ptr_->end_); } template inline const char* type_name (InputIter, const T*) { return "InputIterator"; } template inline OutputIter make_iter (T *cur, const T *begin, const T *end, const OutputIter&) { return OutputIter(cur, begin, end); } template inline OutputIter copy_iter (const OutputIter &it, const T*) { return OutputIter(it.cur_, 0, it.ptr_->end); } template inline const char* type_name (OutputIter, const T*) { return "OutputIterator"; } template inline FwdIter make_iter (T *cur, const T *begin, const T *end, const FwdIter&) { return FwdIter(cur, begin, end); } template inline FwdIter copy_iter (const FwdIter &it, const T*) { return FwdIter(it.cur_, 0, it.end_); } template inline const char* type_name (FwdIter, const T*) { return "ForwardIterator"; } template inline ConstFwdIter make_iter (const T *cur, const T *begin, const T *end, const ConstFwdIter&) { return ConstFwdIter(cur, begin, end); } template inline ConstFwdIter copy_iter (const ConstFwdIter &it, const T*) { return ConstFwdIter(it.cur_, 0, it.end_); } template inline const char* type_name (ConstFwdIter, const T*) { return "ConstForwardIterator"; } template inline BidirIter make_iter (T *cur, const T *begin, const T *end, const BidirIter&) { return BidirIter(cur, begin, end); } template inline BidirIter copy_iter (const BidirIter &it, const T*) { return BidirIter(it.cur_, it.begin_, it.end_); } template inline const char* type_name (BidirIter, const T*) { return "BidirectionalIterator"; } template inline ConstBidirIter make_iter (const T *cur, const T *begin, const T *end, const ConstBidirIter&) { return ConstBidirIter(cur, begin, end); } template inline ConstBidirIter copy_iter (const ConstBidirIter &it, const T*) { return ConstBidirIter(it.cur_, it.begin_, it.end_); } template inline const char* type_name (ConstBidirIter, const T*) { return "ConstBidirectionalIterator"; } template inline RandomAccessIter make_iter (T *cur, const T *begin, const T *end, const RandomAccessIter&) { return RandomAccessIter(cur, begin, end); } template inline RandomAccessIter copy_iter (const RandomAccessIter &it, const T*) { return RandomAccessIter(it.cur_, it.begin_, it.end_); } template inline const char* type_name (RandomAccessIter, const T*) { return "RandomAccessIterator"; } template inline ConstRandomAccessIter make_iter (const T *cur, const T *begin, const T *end, const ConstRandomAccessIter&) { return ConstRandomAccessIter(cur, begin, end); } template inline ConstRandomAccessIter copy_iter (const ConstRandomAccessIter &it, const T*) { return ConstRandomAccessIter(it.cur_, it.begin_, it.end_); } template inline const char* type_name (ConstRandomAccessIter, const T*) { return "ConstRandomAccessIterator"; } // temporary to not break the tests which uses struct X #include #endif // RW_ALG_TEST_H_INCLUDED