sl@0: /*************************************************************************** sl@0: * sl@0: * alg_test.h - common definitions for algorithms tests sl@0: * sl@0: * $Id: alg_test.h 349021 2005-11-25 20:32:27Z sebor $ sl@0: * sl@0: *************************************************************************** sl@0: * sl@0: * Copyright (c) 1994-2005 Quovadx, Inc., acting through its Rogue Wave sl@0: * Software division. Licensed under the Apache License, Version 2.0 (the sl@0: * "License"); you may not use this file except in compliance with the sl@0: * License. You may obtain a copy of the License at sl@0: * http://www.apache.org/licenses/LICENSE-2.0. Unless required by sl@0: * applicable law or agreed to in writing, software distributed under sl@0: * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR sl@0: * CONDITIONS OF ANY KIND, either express or implied. See the License sl@0: * for the specific language governing permissions and limitations under sl@0: * the License. sl@0: * sl@0: **************************************************************************/ sl@0: sl@0: #ifndef _RWSTD_ALG_TEST_H_INCLUDED sl@0: #define _RWSTD_ALG_TEST_H_INCLUDED sl@0: sl@0: #include sl@0: sl@0: #include // for assert() sl@0: sl@0: #include sl@0: #include "rw/_defs.h" sl@0: sl@0: sl@0: // defining macro for var sl@0: #define n_total_op_assign_ (*Getn_total_op_assign_()) sl@0: #define n_total_op_eq_ (*Getn_total_op_eq_()) sl@0: #define gen_ (* Get_gen_()) sl@0: // objects of class X maintain a count of their instances in existence, sl@0: // the number of defaut and copy ctor calls, assignment operators, and sl@0: // the number of calls to operator==() and operator<() sl@0: struct _TEST_EXPORT X sl@0: { sl@0: const int id_; // a unique non-zero id of the object sl@0: int origin_; // id of the original object that this sl@0: // is a (perhaps indirect) copy of (id_ sl@0: // when this is the original) sl@0: int src_id_; // id of the object that this is a direct sl@0: // copy of (id_ when this the original) sl@0: int val_; // object's value sl@0: sl@0: // number of times the object has been copied into another object, sl@0: // regardless of whether the operation threw an exception or not sl@0: _RWSTD_SIZE_T n_copy_ctor_; sl@0: sl@0: // number of times the object's assignment operator has been invoked, sl@0: // regardless of whether the operation threw an exception or not sl@0: _RWSTD_SIZE_T n_op_assign_; sl@0: sl@0: // number of times the object's operator== was invoked sl@0: // regardless of whether the operation threw an exception sl@0: _RWSTD_SIZE_T n_op_eq_; sl@0: sl@0: // number of times the object's operator< was invoked sl@0: // regardless of whether the operation threw an exception sl@0: _RWSTD_SIZE_T n_op_lt_; sl@0: sl@0: static _RWSTD_SIZE_T count_; // number of objects in existence (>= 0) sl@0: static int id_gen_; // generates a unique non-zero id sl@0: _TEST_EXPORT static int (*_gen_)(); // extern "C++" int (*)() sl@0: sl@0: _TEST_EXPORT static _RWSTD_SIZE_T n_total_def_ctor_; // number of default ctor calls sl@0: _TEST_EXPORT static _RWSTD_SIZE_T n_total_copy_ctor_; // ... copy ctors ... sl@0: _TEST_EXPORT static _RWSTD_SIZE_T n_total_dtor_; // ... dtors ... sl@0: //new chnage decl of member var sl@0: _TEST_EXPORT static _RWSTD_SIZE_T _n_total_op_assign_; // ... assignment operators ... sl@0: _TEST_EXPORT static _RWSTD_SIZE_T _n_total_op_eq_; // ... equality operators ... sl@0: _TEST_EXPORT static _RWSTD_SIZE_T n_total_op_lt_; // ... operators <= ... sl@0: sl@0: // classes thrown from the respective functions sl@0: struct Exception { int id_; }; sl@0: struct DefCtor: Exception { }; sl@0: struct CopyCtor: Exception { }; sl@0: struct Dtor: Exception { }; sl@0: struct OpAssign: Exception { }; sl@0: struct OpEq: Exception { }; sl@0: struct OpLt: Exception { }; sl@0: sl@0: // throw object's `id' wrapped in the appropriate struct when the sl@0: // corresponding n_total_xxx_ counter reaches the value pointed to sl@0: // by the respective pointer below sl@0: static _RWSTD_SIZE_T* def_ctor_throw_ptr_; sl@0: static _RWSTD_SIZE_T* copy_ctor_throw_ptr_; sl@0: static _RWSTD_SIZE_T* dtor_throw_ptr_; sl@0: static _RWSTD_SIZE_T* op_assign_throw_ptr_; sl@0: static _RWSTD_SIZE_T* op_eq_throw_ptr_; sl@0: static _RWSTD_SIZE_T* op_lt_throw_ptr_; sl@0: sl@0: // objects to which the pointers above initally point sl@0: static _RWSTD_SIZE_T def_ctor_throw_count_; sl@0: static _RWSTD_SIZE_T copy_ctor_throw_count_; sl@0: static _RWSTD_SIZE_T dtor_throw_count_; sl@0: static _RWSTD_SIZE_T op_assign_throw_count_; sl@0: static _RWSTD_SIZE_T op_eq_throw_count_; sl@0: static _RWSTD_SIZE_T op_lt_throw_count_; sl@0: sl@0: _TEST_EXPORT X (); sl@0: sl@0: _TEST_EXPORT X (const X&); sl@0: sl@0: _TEST_EXPORT ~X (); sl@0: sl@0: _TEST_EXPORT X& operator= (const X&); sl@0: sl@0: _TEST_EXPORT bool operator== (const X&) const; sl@0: _TEST_EXPORT bool operator< (const X&) const; sl@0: sl@0: // the following operators are not declared or defined in order sl@0: // to detect any unwarranted assumptions made in algorithms sl@0: // bool operator!= (const X &rhs) const; sl@0: // bool operator> (const X &rhs) const; sl@0: // bool operator>= (const X &rhs) const; sl@0: // bool operator<= (const X &rhs) const; sl@0: // X operator- () const; sl@0: // X operator+ () const; sl@0: sl@0: _TEST_EXPORT bool sl@0: is_count (_RWSTD_SIZE_T copy_ctor, sl@0: _RWSTD_SIZE_T op_assign, sl@0: _RWSTD_SIZE_T op_eq, sl@0: _RWSTD_SIZE_T op_lt) const; sl@0: sl@0: _TEST_EXPORT static bool sl@0: is_total (_RWSTD_SIZE_T count, sl@0: _RWSTD_SIZE_T n_def_ctor, sl@0: _RWSTD_SIZE_T n_copy_ctor, sl@0: _RWSTD_SIZE_T n_op_assign, sl@0: _RWSTD_SIZE_T n_op_eq, sl@0: _RWSTD_SIZE_T n_op_lt); sl@0: sl@0: _TEST_EXPORT static void reset_totals (); sl@0: sl@0: // construct an array of objects of type X each initialized sl@0: // from the corresponding element of the character array sl@0: static X* from_char (const char*, _RWSTD_SIZE_T = ~0UL); sl@0: sl@0: // returns -1 when less, 0 when same, or +1 when the array sl@0: // of X objects is greater than the character string sl@0: static int compare (const X*, const char*, _RWSTD_SIZE_T = ~0UL); sl@0: static int compare (const char*, const X*, _RWSTD_SIZE_T = ~0UL); sl@0: sl@0: // returns -1 when less, 0 when same, or +1 when the first sl@0: // array of X objects is greater than the second array sl@0: static int compare (const X*, const X*, _RWSTD_SIZE_T); sl@0: }; sl@0: sl@0: sl@0: struct _TEST_EXPORT UnaryPredicate sl@0: { sl@0: // total number of times operator() was invoked sl@0: static _RWSTD_SIZE_T n_total_op_fcall_; sl@0: sl@0: UnaryPredicate (); sl@0: sl@0: UnaryPredicate (const UnaryPredicate&); sl@0: sl@0: UnaryPredicate& operator= (const UnaryPredicate&); sl@0: sl@0: virtual ~UnaryPredicate (); sl@0: sl@0: virtual bool operator()(const X&) const; sl@0: }; sl@0: sl@0: sl@0: struct _TEST_EXPORT BinaryPredicate sl@0: { sl@0: // total number of times operator() was invoked sl@0: static _RWSTD_SIZE_T n_total_op_fcall_; sl@0: sl@0: bool ignore_case_; sl@0: sl@0: BinaryPredicate (bool = false); sl@0: sl@0: BinaryPredicate (const BinaryPredicate&); sl@0: sl@0: BinaryPredicate& operator= (const BinaryPredicate&); sl@0: sl@0: virtual ~BinaryPredicate (); sl@0: sl@0: virtual bool operator()(const X&, const X&) const; sl@0: }; sl@0: sl@0: sl@0: class _TEST_EXPORT tempstr; sl@0: sl@0: // converts a sequence of objects of type X to a tempstr object sl@0: // in the format "[%p0, %p1): { x0, >x1<, ..., xN - 1 } where N sl@0: // is defined as: N = (X*)p1 - (X*)p0 sl@0: // the last argument, if non-negative, indicates the index of the sl@0: // element enclosed in between the '>' and '<' characters sl@0: _TEST_EXPORT void to_string (tempstr*, const X*, const X*, int = -1); sl@0: sl@0: sl@0: // generate a unique sequential number starting from 0 sl@0: _TEST_EXPORT int gen_seq (); sl@0: sl@0: // generate numbers in the sequence 0, 0, 1, 1, 2, 2, 3, 3, etc... sl@0: _TEST_EXPORT int gen_seq_2lists (); sl@0: sl@0: // generate a sequence of subsequences (i.e., 0, 1, 2, 3, 4, 0, 1, 2, etc...) sl@0: _TEST_EXPORT int gen_subseq (); sl@0: sl@0: // wrapper around a (possibly) extern "C" int rand() sl@0: // extern "C++" sl@0: _TEST_EXPORT int gen_rnd (); sl@0: sl@0: sl@0: // computes an integral log2 sl@0: inline unsigned ilog2 (unsigned long n) sl@0: { sl@0: unsigned result = 0; sl@0: while (n >>= 1) sl@0: ++result; sl@0: return result; sl@0: } sl@0: sl@0: sl@0: // computes an integral log10 sl@0: inline unsigned ilog10 (unsigned long n) sl@0: { sl@0: unsigned result = 0; sl@0: while (n /= 10) sl@0: ++result; sl@0: return result; sl@0: } sl@0: sl@0: sl@0: // returns true iff a sequence of (not necessarily unique) values sl@0: // is sorted in an ascending order sl@0: template sl@0: inline bool is_sorted_lt (InputIterator first, InputIterator last) sl@0: { sl@0: if (first == last) sl@0: return true; sl@0: sl@0: for (InputIterator prev (first); ++first != last; prev = first) { sl@0: if (*first < *prev) sl@0: return false; sl@0: } sl@0: sl@0: return true; sl@0: } sl@0: sl@0: sl@0: // returns true iff a sequence of (not necessarily unique) values sl@0: // is sorted in a descending order sl@0: template sl@0: inline bool is_sorted_gt (InputIterator first, InputIterator last) sl@0: { sl@0: if (first == last) sl@0: return true; sl@0: sl@0: for (InputIterator prev (first); ++first != last; prev = first) { sl@0: if (*prev < *first) sl@0: return false; sl@0: } sl@0: sl@0: return true; sl@0: } sl@0: sl@0: sl@0: // type used to exercise that algorithms do not apply operators sl@0: // to function objects the latter are not required to define sl@0: struct conv_to_bool { sl@0: sl@0: static conv_to_bool make (bool val) { sl@0: conv_to_bool tmp; sl@0: tmp.val_ = val; sl@0: return tmp; sl@0: } sl@0: sl@0: operator bool () const { sl@0: return val_; sl@0: } sl@0: sl@0: public: sl@0: bool operator!() const sl@0: { sl@0: return val_ != 0; sl@0: } // not defined sl@0: sl@0: bool val_; sl@0: }; sl@0: sl@0: // not defined sl@0: void operator&& (const conv_to_bool&, bool); sl@0: void operator&& (bool, const conv_to_bool&); sl@0: void operator|| (const conv_to_bool&, bool); sl@0: void operator|| (bool, const conv_to_bool&); sl@0: sl@0: // element-type prototypes to exercise container requirements sl@0: sl@0: sl@0: // meets requirements listed at 25, p7 sl@0: template sl@0: struct predicate { sl@0: conv_to_bool operator() (const T &a) const { sl@0: _RWSTD_UNUSED (a); sl@0: return conv_to_bool::make (true); sl@0: } sl@0: }; sl@0: sl@0: sl@0: // meets requirements listed at 25, p8 sl@0: template sl@0: struct binary_predicate { sl@0: conv_to_bool operator() (const T &a, const T &b) const { sl@0: _RWSTD_UNUSED (a); sl@0: _RWSTD_UNUSED (b); sl@0: return conv_to_bool::make (true); sl@0: } sl@0: }; sl@0: sl@0: sl@0: // meets requirements listed at 25.2.3, p2 sl@0: template sl@0: struct func { sl@0: typedef T argument_type; sl@0: typedef argument_type& reference; sl@0: sl@0: reference operator() (const argument_type&) const { sl@0: return _RWSTD_REINTERPRET_CAST (reference, sl@0: _RWSTD_CONST_CAST (func*, this)->dummy); sl@0: } sl@0: sl@0: private: sl@0: char dummy; sl@0: }; sl@0: sl@0: sl@0: // meets requirements listed at 25.2.3, p2 sl@0: template sl@0: struct binary_func { sl@0: typedef T argument_type; sl@0: typedef argument_type& reference; sl@0: sl@0: reference operator() (const argument_type&, sl@0: const argument_type&) const { sl@0: return _RWSTD_REINTERPRET_CAST (reference, sl@0: _RWSTD_CONST_CAST (binary_func*, this)->dummy); sl@0: } sl@0: sl@0: private: sl@0: char dummy; sl@0: }; sl@0: sl@0: sl@0: // a base-class to extend the requirements classes from sl@0: sl@0: enum { no_ctor = 0, def_ctor = 1, cpy_ctor = 2 }; sl@0: sl@0: template sl@0: struct base; sl@0: sl@0: sl@0: template<> sl@0: struct base sl@0: { sl@0: private: sl@0: // struct s added to prevent gcc warning: base has a private sl@0: // constructor and no friends sl@0: struct s { }; sl@0: friend struct s; sl@0: sl@0: base (); sl@0: base (const base&); sl@0: void operator= (base&); sl@0: }; sl@0: sl@0: sl@0: template<> sl@0: struct base sl@0: { sl@0: base () : unused (0) { } sl@0: sl@0: private: sl@0: sl@0: void operator= (base&); sl@0: base (const base&); sl@0: sl@0: // unused member prevents bogus HP aCC warnings (see Onyx #23561) sl@0: int unused; sl@0: }; sl@0: sl@0: sl@0: template<> sl@0: struct base sl@0: { sl@0: // explicitly specifying redundant template parameters to work sl@0: // around a SunPro 5.2 bug (see Onyx #24260) sl@0: base (const base &rhs): unused (rhs.unused) { } sl@0: sl@0: private: sl@0: sl@0: base (); sl@0: void operator= (base&); sl@0: sl@0: // unused member prevents bogus HP aCC warnings (see Onyx #23561) sl@0: int unused; sl@0: }; sl@0: sl@0: sl@0: template<> sl@0: struct base<(def_ctor | cpy_ctor)> sl@0: { sl@0: base (): unused (0) { } sl@0: sl@0: // explicitly specifying redundant template parameters to work sl@0: // around a SunPro 5.2 bug (see Onyx #24260) sl@0: base (const base<(def_ctor | cpy_ctor)> &rhs): unused (rhs.unused) { } sl@0: sl@0: private: sl@0: sl@0: void operator= (base&); sl@0: sl@0: // unused member prevents bogus HP aCC warnings (see Onyx #23561) sl@0: int unused; sl@0: }; sl@0: sl@0: sl@0: template sl@0: struct eq_comp: T { }; sl@0: sl@0: sl@0: template sl@0: inline bool operator== (const eq_comp&, const eq_comp&) sl@0: { sl@0: return true; sl@0: } sl@0: sl@0: sl@0: template sl@0: struct lt_comp: T { }; sl@0: sl@0: sl@0: template sl@0: inline bool operator< (const lt_comp&, const lt_comp&) sl@0: { sl@0: return true; sl@0: } sl@0: sl@0: sl@0: // assignment sl@0: sl@0: template sl@0: struct assign : T sl@0: { sl@0: assign& operator= (const assign& rhs) { sl@0: unused = rhs.unused; sl@0: return *this; sl@0: } sl@0: private: sl@0: // unused member prevents bogus HP aCC warnings (see Onyx #23561) sl@0: int unused; sl@0: }; sl@0: sl@0: sl@0: // conversion structs sl@0: sl@0: // struct split into 2 to eliminate the following g++ 2.95.2 warning: sl@0: // warning: choosing `convert::operator U&()' over sl@0: // `convert::operator const U&() const' sl@0: sl@0: template sl@0: struct cvt : T sl@0: { sl@0: operator U& () { sl@0: return _RWSTD_REINTERPRET_CAST (U&, *this); sl@0: } sl@0: }; sl@0: sl@0: sl@0: template sl@0: struct const_cvt : T sl@0: { sl@0: operator const U& () const { sl@0: return _RWSTD_REINTERPRET_CAST (const U&, *this); sl@0: } sl@0: }; sl@0: sl@0: sl@0: #ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC sl@0: sl@0: struct DummyBase { }; sl@0: sl@0: # define ITER_BASE(ign1, ign2, ign3, ign4, ign5) DummyBase sl@0: #else // if defined (_RWSTD_NO_CLASS_PARTIAL_SPEC) sl@0: // when partial specialization isn't supported sl@0: # define ITER_BASE(Cat, T, Dist, Ptr, Ref) \ sl@0: std::iterator sl@0: #endif // _RWSTD_NO_CLASS_PARTIAL_SPEC sl@0: sl@0: sl@0: // satisfies the requirements in 24.1.1 [lib.input.iterators] sl@0: template sl@0: struct InputIter: ITER_BASE (std::input_iterator_tag, T, int, T*, T&) sl@0: { sl@0: typedef T value_type; sl@0: typedef value_type* pointer; sl@0: typedef value_type& reference; sl@0: typedef int difference_type; sl@0: typedef std::input_iterator_tag iterator_category; sl@0: sl@0: // body shared by all copies of the same InputIter specialization sl@0: // to detect algorithms that pass through the same interator more sl@0: // than once (disallowed by 24.1.1, p3) sl@0: struct Shared { sl@0: const value_type *cur_; sl@0: const value_type *beg_; sl@0: const value_type *end_; sl@0: int ref_; sl@0: sl@0: Shared (const value_type *cur, sl@0: const value_type *beg, sl@0: const value_type *end) sl@0: : cur_ (cur), beg_ (beg), end_ (end), ref_ (1) { } sl@0: sl@0: ~Shared () { sl@0: cur_ = beg_ = end_ = 0; sl@0: ref_ = -1; sl@0: } sl@0: sl@0: private: sl@0: Shared (const Shared&); // not defined sl@0: void operator= (const Shared&); // not defined sl@0: sl@0: }; sl@0: sl@0: // InputIterators are not default constructible sl@0: InputIter (const value_type *cur, sl@0: const value_type *beg, sl@0: const value_type *end) sl@0: : ptr_ (new Shared (cur, beg, end)), cur_ (cur) { } sl@0: sl@0: InputIter (const InputIter &rhs) sl@0: : ptr_ (rhs.ptr_), cur_ (rhs.cur_) { sl@0: assert (0 != ptr_); sl@0: ++ptr_->ref_; sl@0: } sl@0: sl@0: ~InputIter () { sl@0: assert (0 != ptr_); sl@0: sl@0: if (0 == --ptr_->ref_) // decrement the reference count sl@0: delete ptr_; sl@0: ptr_ = 0; sl@0: cur_ = 0; sl@0: } sl@0: sl@0: InputIter& operator= (const InputIter &rhs) { sl@0: assert (rhs == rhs); // assert `rhs' is valid sl@0: sl@0: assert (0 != ptr_); sl@0: if (0 == --ptr_->ref_) sl@0: delete ptr_; sl@0: sl@0: ptr_ = rhs.ptr_; sl@0: sl@0: assert (0 != ptr_); sl@0: ++ptr_->ref_; sl@0: sl@0: cur_ = rhs.cur_; sl@0: sl@0: return *this; sl@0: } sl@0: sl@0: bool operator== (const InputIter &rhs) const { sl@0: // assert that both arguments are in the domain of operator==() sl@0: // i.e., that no copy of *this or `rhs' has been incremented sl@0: // and that no copy passed through this value of the iterator sl@0: sl@0: assert (0 != ptr_); sl@0: assert (cur_ == ptr_->cur_); sl@0: sl@0: assert (0 != rhs.ptr_); sl@0: assert (rhs.cur_ == rhs.ptr_->cur_); sl@0: sl@0: return cur_ == rhs.cur_; sl@0: } sl@0: sl@0: bool operator!= (const InputIter &rhs) const { sl@0: return !(*this == rhs); sl@0: } sl@0: sl@0: // returning const-reference rather than a value in order sl@0: // not to impose the CopyConstructible requirement on T sl@0: // and to disallow constructs like *InputIter() = T() sl@0: const value_type& operator* () const { sl@0: assert (*this == *this); // assert *this is valid sl@0: assert (cur_ < ptr_->end_); // assert *this is dereferenceable sl@0: return *cur_; sl@0: } sl@0: sl@0: _RWSTD_OPERATOR_ARROW(const value_type* operator-> () const); sl@0: sl@0: InputIter& operator++ () { sl@0: assert (*this == *this); // assert *this is valid sl@0: assert (cur_ < ptr_->end_); // assert *this is not past the end sl@0: sl@0: ptr_->cur_ = ++cur_; sl@0: sl@0: return *this; sl@0: } sl@0: sl@0: InputIter operator++ (int) { sl@0: return ++*this; sl@0: } sl@0: sl@0: // private: sl@0: Shared *ptr_; sl@0: const value_type *cur_; // past-the-end sl@0: }; sl@0: sl@0: sl@0: // satisfies the requirements in 24.1.2 [lib.output.iterators] sl@0: template sl@0: struct OutputIter: ITER_BASE (std::output_iterator_tag, T, int, T*, T&) sl@0: { sl@0: typedef T value_type; sl@0: typedef value_type* pointer; sl@0: typedef value_type& reference; sl@0: typedef int difference_type; sl@0: typedef std::output_iterator_tag iterator_category; sl@0: sl@0: // body shared by all copies of the same OutputIter specialization sl@0: // to detect algorithms that pass through the same interator more sl@0: // than once (disallowed by 24.1.2, p2) sl@0: struct Shared { sl@0: pointer cur_; sl@0: pointer assign_; sl@0: const value_type *begin_; sl@0: const value_type *end_; sl@0: int ref_; sl@0: sl@0: Shared (pointer cur, const value_type *end) sl@0: : cur_ (cur), assign_ (cur), begin_ (cur), end_ (end), ref_ (1) { } sl@0: sl@0: ~Shared () { sl@0: begin_ = end_ = cur_ = assign_ = 0; sl@0: ref_ = -1; sl@0: } sl@0: sl@0: private: sl@0: Shared (const Shared&); // not defined sl@0: void operator= (const Shared&); // not defined sl@0: sl@0: }; sl@0: sl@0: // class whose objects are returned from OutputIter::operator* sl@0: // to detect multiple assignments (disallowed by 24.1.2, p2) sl@0: class Proxy { sl@0: friend struct OutputIter; sl@0: sl@0: Shared* const ptr_; sl@0: sl@0: Proxy (Shared *ptr): ptr_ (ptr) { } sl@0: sl@0: public: sl@0: void operator= (const value_type &rhs) { sl@0: assert (0 != ptr_); sl@0: sl@0: // verify that the iterator is in the valid range sl@0: assert (ptr_->cur_ >= ptr_->begin_ && ptr_->cur_ <= ptr_->end_); sl@0: sl@0: // verify that the assignment point is the same as the current sl@0: // position `cur' within the sequence or immediately before it sl@0: // (in order to allow the expression: *it++ = val) sl@0: assert ( ptr_->assign_ == ptr_->cur_ sl@0: || ptr_->assign_ + 1 == ptr_->cur_); sl@0: sl@0: // assign and increment the assignment point sl@0: *ptr_->assign_++ = rhs; sl@0: } sl@0: }; sl@0: sl@0: // OutputIterators are not default constructible sl@0: OutputIter (pointer cur, sl@0: const value_type *, sl@0: const value_type *end) sl@0: : ptr_ (new Shared (cur, end)), cur_ (cur) { } sl@0: sl@0: OutputIter (const OutputIter &rhs) sl@0: : ptr_ (rhs.ptr_), cur_ (rhs.cur_) { sl@0: ++ptr_->ref_; // increment the reference count sl@0: } sl@0: sl@0: ~OutputIter () { sl@0: if (0 == --ptr_->ref_) // decrement the reference count sl@0: delete ptr_; sl@0: ptr_ = 0; sl@0: cur_ = 0; sl@0: } sl@0: sl@0: OutputIter& operator= (const OutputIter &rhs) { sl@0: if (0 == --ptr_->ref_) sl@0: delete ptr_; sl@0: sl@0: ptr_ = rhs.ptr_; sl@0: ++ptr_->ref_; sl@0: sl@0: cur_ = rhs.cur_; sl@0: sl@0: return *this; sl@0: } sl@0: sl@0: void operator= (const value_type &rhs) const { sl@0: **this = rhs; sl@0: } sl@0: sl@0: // return a proxy in order to detect multiple assignments sl@0: // through the iterator (disallowed by 24.1.2, p2)) sl@0: Proxy operator* () const { sl@0: assert (0 != ptr_); sl@0: assert (ptr_->assign_ && ptr_->assign_ != ptr_->end_); sl@0: sl@0: return Proxy (ptr_); sl@0: } sl@0: sl@0: _RWSTD_OPERATOR_ARROW (pointer operator-> () const); sl@0: sl@0: OutputIter& operator++ () { sl@0: assert (cur_ == ptr_->cur_); sl@0: assert (ptr_->cur_ >= ptr_->begin_ && ptr_->cur_ < ptr_->end_); sl@0: cur_ = ++ptr_->cur_; sl@0: return *this; sl@0: } sl@0: sl@0: // returning a const value rather than a modifiable value sl@0: // in order to verify the requirement in row 5 of Table 73 sl@0: const OutputIter operator++ (int) { sl@0: OutputIter tmp (*this); sl@0: return ++*this, tmp; sl@0: } sl@0: sl@0: // private: sl@0: Shared *ptr_; sl@0: pointer cur_; sl@0: }; sl@0: sl@0: sl@0: // satisfies the requirements in 24.1.3 [lib.forward.iterators] sl@0: template sl@0: struct FwdIter: ITER_BASE (std::forward_iterator_tag, T, int, T*, T&) sl@0: { sl@0: typedef T value_type; sl@0: typedef value_type* pointer; sl@0: typedef value_type& reference; sl@0: typedef int difference_type; sl@0: typedef std::forward_iterator_tag iterator_category; sl@0: sl@0: FwdIter (): cur_ (0), end_ (0) { } sl@0: sl@0: FwdIter (pointer cur, sl@0: const value_type *, sl@0: const value_type *end) sl@0: : cur_ (cur), end_ (end) { } sl@0: sl@0: FwdIter (const FwdIter &rhs) sl@0: : cur_ (rhs.cur_), end_ (rhs.end_) { } sl@0: sl@0: ~FwdIter () { sl@0: end_ = cur_ = 0; sl@0: } sl@0: sl@0: FwdIter& operator= (const FwdIter &rhs) { sl@0: cur_ = rhs.cur_; sl@0: end_ = rhs.end_; sl@0: return *this; sl@0: } sl@0: sl@0: bool operator== (const FwdIter &rhs) const { sl@0: assert (cur_ != 0); sl@0: return cur_ == rhs.cur_; sl@0: } sl@0: sl@0: bool operator!= (const FwdIter &rhs) const { sl@0: return !(*this == rhs); sl@0: } sl@0: sl@0: reference operator* () const { sl@0: assert (cur_ != 0 && cur_ != end_); sl@0: return *cur_; sl@0: } sl@0: sl@0: _RWSTD_OPERATOR_ARROW (pointer operator-> () const); sl@0: sl@0: FwdIter& operator++ () { sl@0: assert (cur_ != 0 && cur_ != end_); sl@0: return ++cur_, *this; sl@0: } sl@0: sl@0: FwdIter operator++ (int) { sl@0: FwdIter tmp (*this); sl@0: return ++*this, tmp; sl@0: } sl@0: sl@0: // private: sl@0: pointer cur_; // pointer to current element sl@0: const value_type *end_; // past-the-end sl@0: }; sl@0: sl@0: sl@0: template sl@0: struct ConstFwdIter: FwdIter sl@0: { sl@0: typedef T value_type; sl@0: typedef FwdIter Base; sl@0: sl@0: ConstFwdIter (): Base () { } sl@0: sl@0: ConstFwdIter (const value_type *cur, sl@0: const value_type *begin, sl@0: const value_type *end) sl@0: : Base (_RWSTD_CONST_CAST (value_type*, cur), begin, end) { } sl@0: sl@0: const value_type& operator* () const { sl@0: return Base::operator* (); sl@0: } sl@0: sl@0: _RWSTD_OPERATOR_ARROW (const value_type* operator-> () const); sl@0: }; sl@0: sl@0: sl@0: // satisfies the requirements in 24.1.4 [lib.bidirectional.iterators] sl@0: template sl@0: struct BidirIter: ITER_BASE (std::bidirectional_iterator_tag, T, int, T*, T&) sl@0: { sl@0: typedef T value_type; sl@0: typedef value_type* pointer; sl@0: typedef value_type& reference; sl@0: typedef int difference_type; sl@0: typedef std::bidirectional_iterator_tag iterator_category; sl@0: sl@0: BidirIter (): cur_ (0), begin_ (0), end_ (0) { } sl@0: sl@0: BidirIter (pointer cur, sl@0: const value_type *begin, sl@0: const value_type *end) sl@0: : cur_ (cur), begin_ (begin), end_ (end) { } sl@0: sl@0: BidirIter (const BidirIter &rhs) sl@0: : cur_ (rhs.cur_), begin_ (rhs.begin_), end_ (rhs.end_) { } sl@0: sl@0: ~BidirIter () { sl@0: begin_ = end_ = cur_ = 0; sl@0: } sl@0: sl@0: BidirIter& operator= (const BidirIter &rhs) { sl@0: cur_ = rhs.cur_; sl@0: end_ = rhs.end_; sl@0: return *this; sl@0: } sl@0: sl@0: bool operator== (const BidirIter &rhs) const { sl@0: assert (cur_ != 0 && rhs.cur_ != 0); sl@0: return cur_ == rhs.cur_; sl@0: } sl@0: sl@0: bool operator!= (const BidirIter &rhs) const { sl@0: return !(*this == rhs); sl@0: } sl@0: sl@0: reference operator* () const { sl@0: assert (cur_ != 0 && cur_ != end_); sl@0: return *cur_; sl@0: } sl@0: sl@0: _RWSTD_OPERATOR_ARROW (pointer operator-> () const); sl@0: sl@0: BidirIter& operator++ () { sl@0: assert (cur_ != 0 && cur_ != end_); sl@0: return ++cur_, *this; sl@0: } sl@0: sl@0: BidirIter operator++ (int) { sl@0: BidirIter tmp (*this); sl@0: return ++*this, tmp; sl@0: } sl@0: sl@0: BidirIter& operator-- () { sl@0: assert (cur_ != 0 && cur_ != begin_); sl@0: return --cur_, *this; sl@0: } sl@0: sl@0: BidirIter operator-- (int) { sl@0: BidirIter tmp (*this); sl@0: return --*this, tmp; sl@0: } sl@0: sl@0: // private: sl@0: pointer cur_; // pointer to current element sl@0: const value_type *begin_; // first in range sl@0: const value_type *end_; // past-the-end sl@0: }; sl@0: sl@0: sl@0: template sl@0: struct ConstBidirIter: BidirIter sl@0: { sl@0: typedef T value_type; sl@0: typedef BidirIter Base; sl@0: sl@0: ConstBidirIter (): Base () { } sl@0: sl@0: ConstBidirIter (const value_type *cur, sl@0: const value_type *begin, sl@0: const value_type *end) sl@0: : Base (_RWSTD_CONST_CAST (value_type*, cur), begin, end) { } sl@0: sl@0: const value_type& operator* () const { sl@0: return Base::operator* (); sl@0: } sl@0: sl@0: _RWSTD_OPERATOR_ARROW (const value_type* operator-> () const); sl@0: }; sl@0: sl@0: sl@0: // satisfies the requirements in 24.1.5 [lib.random.access.iterators] sl@0: template sl@0: struct RandomAccessIter sl@0: : ITER_BASE (std::random_access_iterator_tag, T, int, T*, T&) sl@0: { sl@0: typedef T value_type; sl@0: typedef value_type* pointer; sl@0: typedef value_type& reference; sl@0: typedef int difference_type; sl@0: typedef std::random_access_iterator_tag iterator_category; sl@0: sl@0: RandomAccessIter (): cur_ (0), begin_ (0), end_ (0) { } sl@0: sl@0: RandomAccessIter (pointer cur, sl@0: const value_type *begin, sl@0: const value_type *end) sl@0: : cur_ (cur), begin_ (begin), end_ (end) { } sl@0: sl@0: RandomAccessIter (const RandomAccessIter &rhs) sl@0: : cur_ (rhs.cur_), begin_ (rhs.begin_), end_ (rhs.end_) { } sl@0: sl@0: ~RandomAccessIter () { sl@0: begin_ = end_ = cur_ = 0; sl@0: } sl@0: sl@0: RandomAccessIter& operator= (const RandomAccessIter &rhs) { sl@0: cur_ = rhs.cur_; sl@0: begin_ = rhs.begin_; sl@0: end_ = rhs.end_; sl@0: return *this; sl@0: } sl@0: sl@0: reference operator* () const { sl@0: assert (cur_ != 0 && cur_ != end_); sl@0: return *cur_; sl@0: } sl@0: sl@0: _RWSTD_OPERATOR_ARROW (pointer operator-> () const); sl@0: sl@0: RandomAccessIter& operator++ () { sl@0: assert (cur_ != 0 && cur_ != end_); sl@0: return ++cur_, *this; sl@0: } sl@0: sl@0: RandomAccessIter operator++ (int) { sl@0: RandomAccessIter tmp (*this); sl@0: return ++*this, tmp; sl@0: } sl@0: sl@0: RandomAccessIter& operator-- () { sl@0: assert (cur_ != 0 && cur_ != begin_); sl@0: return --cur_, *this; sl@0: } sl@0: sl@0: RandomAccessIter operator-- (int) { sl@0: RandomAccessIter tmp (*this); sl@0: return --*this, tmp; sl@0: } sl@0: sl@0: RandomAccessIter& operator+= (difference_type n) { sl@0: assert ( cur_ != 0 sl@0: && (!end_ || cur_ + n <= end_) sl@0: && (!begin_ || cur_ + n >= begin_)); sl@0: return cur_ += n, *this; sl@0: } sl@0: RandomAccessIter& operator-= (difference_type n) { sl@0: return *this += -n; sl@0: } sl@0: sl@0: RandomAccessIter operator+ (difference_type n) const { sl@0: return RandomAccessIter (*this) += n; sl@0: } sl@0: sl@0: RandomAccessIter operator- (difference_type n) const { sl@0: return RandomAccessIter (*this) -= n; sl@0: } sl@0: sl@0: difference_type operator- (const RandomAccessIter &rhs) const { sl@0: assert (cur_ != 0 && rhs.cur_ != 0); sl@0: return cur_ - rhs.cur_; sl@0: } sl@0: sl@0: bool operator== (const RandomAccessIter &rhs) const { sl@0: assert (cur_ != 0 && rhs.cur_ != 0); sl@0: return cur_ == rhs.cur_; sl@0: } sl@0: sl@0: bool operator!= (const RandomAccessIter &rhs) const { sl@0: return !(*this == rhs); sl@0: } sl@0: sl@0: bool operator< (const RandomAccessIter &rhs) const { sl@0: assert (cur_ != 0 && rhs.cur_ != 0); sl@0: return cur_ < rhs.cur_; sl@0: }; sl@0: sl@0: bool operator> (const RandomAccessIter &rhs) const { sl@0: return rhs < *this; sl@0: } sl@0: sl@0: bool operator<= (const RandomAccessIter &rhs) const { sl@0: return !(rhs < *this); sl@0: } sl@0: sl@0: bool operator>= (const RandomAccessIter &rhs) const { sl@0: return !(*this < rhs); sl@0: } sl@0: sl@0: reference operator[] (difference_type inx) const { sl@0: assert ( cur_ != 0 sl@0: && (!end_ || cur_ + inx < end_) sl@0: && !(begin_ || cur_ + inx >= begin_)); sl@0: return cur_ [inx]; sl@0: } sl@0: sl@0: // private: sl@0: pointer cur_; // pointer to current element sl@0: const value_type *begin_; // first in range sl@0: const value_type *end_; // past-the-end sl@0: }; sl@0: sl@0: sl@0: template sl@0: struct ConstRandomAccessIter: RandomAccessIter sl@0: { sl@0: typedef T value_type; sl@0: typedef RandomAccessIter Base; sl@0: typedef typename Base::difference_type difference_type; sl@0: sl@0: ConstRandomAccessIter (): Base () { } sl@0: sl@0: ConstRandomAccessIter (const value_type *cur, sl@0: const value_type *begin, sl@0: const value_type *end) sl@0: : Base (_RWSTD_CONST_CAST (value_type*, cur), begin, end) { } sl@0: sl@0: const value_type& operator* () const { sl@0: return Base::operator* (); sl@0: } sl@0: sl@0: _RWSTD_OPERATOR_ARROW (const value_type* operator-> () const); sl@0: sl@0: const value_type& operator[] (difference_type inx) const { sl@0: return Base::operator[] (inx); sl@0: } sl@0: }; sl@0: sl@0: sl@0: template sl@0: inline T* sl@0: make_iter (T *cur, const T*, const T*, T*) sl@0: { sl@0: return cur; sl@0: } sl@0: sl@0: template sl@0: inline T* sl@0: copy_iter (T *ptr, const T*) sl@0: { sl@0: return ptr; sl@0: } sl@0: sl@0: // dummy function argument provided to help broken compilers (PR #29835) sl@0: sl@0: template sl@0: inline InputIter sl@0: make_iter (const T *cur, const T *begin, const T *end, const InputIter&) sl@0: { sl@0: return InputIter(cur, begin, end); sl@0: } sl@0: sl@0: template sl@0: inline InputIter sl@0: copy_iter (const InputIter &it, const T*) sl@0: { sl@0: return InputIter(it.cur_, it.ptr_->beg_, it.ptr_->end_); sl@0: } sl@0: sl@0: template sl@0: inline const char* type_name (InputIter, const T*) sl@0: { return "InputIterator"; } sl@0: sl@0: sl@0: template sl@0: inline OutputIter sl@0: make_iter (T *cur, const T *begin, const T *end, const OutputIter&) sl@0: { sl@0: return OutputIter(cur, begin, end); sl@0: } sl@0: sl@0: template sl@0: inline OutputIter sl@0: copy_iter (const OutputIter &it, const T*) sl@0: { sl@0: return OutputIter(it.cur_, 0, it.ptr_->end); sl@0: } sl@0: sl@0: template sl@0: inline const char* type_name (OutputIter, const T*) sl@0: { return "OutputIterator"; } sl@0: sl@0: sl@0: template sl@0: inline FwdIter sl@0: make_iter (T *cur, const T *begin, const T *end, FwdIter) sl@0: { sl@0: return FwdIter(cur, begin, end); sl@0: } sl@0: sl@0: template sl@0: inline FwdIter sl@0: copy_iter (const FwdIter &it, const T*) sl@0: { sl@0: return FwdIter(it.cur_, 0, it.end_); sl@0: } sl@0: sl@0: template sl@0: inline const char* type_name (FwdIter, const T*) sl@0: { return "ForwardIterator"; } sl@0: sl@0: sl@0: template sl@0: inline ConstFwdIter sl@0: make_iter (T *cur, const T *begin, const T *end, ConstFwdIter) sl@0: { sl@0: return ConstFwdIter(cur, begin, end); sl@0: } sl@0: sl@0: template sl@0: inline ConstFwdIter sl@0: copy_iter (const ConstFwdIter &it, const T*) sl@0: { sl@0: return ConstFwdIter(it.cur_, 0, it.end_); sl@0: } sl@0: sl@0: template sl@0: inline const char* type_name (ConstFwdIter, const T*) sl@0: { return "ConstForwardIterator"; } sl@0: sl@0: sl@0: template sl@0: inline BidirIter sl@0: make_iter (T *cur, const T *begin, const T *end, BidirIter) sl@0: { sl@0: return BidirIter(cur, begin, end); sl@0: } sl@0: sl@0: template sl@0: inline BidirIter sl@0: copy_iter (const BidirIter &it, const T*) sl@0: { sl@0: return BidirIter(it.cur_, it.begin_, it.end_); sl@0: } sl@0: sl@0: template sl@0: inline const char* type_name (BidirIter, const T*) sl@0: { return "BidirectionalIterator"; } sl@0: sl@0: sl@0: template sl@0: inline ConstBidirIter sl@0: make_iter (T *cur, const T *begin, const T *end, ConstBidirIter) sl@0: { sl@0: return ConstBidirIter(cur, begin, end); sl@0: } sl@0: sl@0: template sl@0: inline ConstBidirIter sl@0: copy_iter (const ConstBidirIter &it, const T*) sl@0: { sl@0: return ConstBidirIter(it.cur_, it.begin_, it.end_); sl@0: } sl@0: sl@0: template sl@0: inline const char* type_name (ConstBidirIter, const T*) sl@0: { return "ConstBidirectionalIterator"; } sl@0: sl@0: sl@0: template sl@0: inline RandomAccessIter sl@0: make_iter (T *cur, const T *begin, const T *end, RandomAccessIter) sl@0: { sl@0: return RandomAccessIter(cur, begin, end); sl@0: } sl@0: sl@0: template sl@0: inline RandomAccessIter sl@0: copy_iter (const RandomAccessIter &it, const T*) sl@0: { sl@0: return RandomAccessIter(it.cur_, it.begin_, it.end_); sl@0: } sl@0: sl@0: template sl@0: inline const char* type_name (RandomAccessIter, const T*) sl@0: { return "RandomAccessIterator"; } sl@0: sl@0: sl@0: template sl@0: inline ConstRandomAccessIter sl@0: make_iter (T *cur, const T *begin, const T *end, ConstRandomAccessIter) sl@0: { sl@0: return ConstRandomAccessIter(cur, begin, end); sl@0: } sl@0: sl@0: template sl@0: inline ConstRandomAccessIter sl@0: copy_iter (const ConstRandomAccessIter &it, const T*) sl@0: { sl@0: return ConstRandomAccessIter(it.cur_, it.begin_, it.end_); sl@0: } sl@0: sl@0: template sl@0: inline const char* type_name (ConstRandomAccessIter, const T*) sl@0: { return "ConstRandomAccessIterator"; } sl@0: sl@0: typedef int (*fptr_gen_)(); sl@0: sl@0: //exporting fun for exporting global var sl@0: _TEST_EXPORT _RWSTD_SIZE_T* Getn_total_op_assign_(); sl@0: _TEST_EXPORT _RWSTD_SIZE_T* Getn_total_op_eq_(); sl@0: _TEST_EXPORT fptr_gen_* Get_gen_(); sl@0: #endif // _RWSTD_ALG_TEST_H_INCLUDED