fork download
  1. enum EComparisonType {
  2. EQ,
  3. NOT_EQ,
  4. LESS,
  5. GREATER,
  6. LESS_OR_EQ,
  7. GREATER_OR_EQ
  8. };
  9.  
  10. template <const EComparisonType>
  11. // Functor
  12. struct Compare {};
  13.  
  14. template<>
  15. struct Compare<EComparisonType::EQ> {
  16. template <typename T, class U>
  17. bool operator()(const T& first, const U& second) throw() {
  18. return first == second;
  19. }
  20. };
  21.  
  22. template<>
  23. struct Compare<EComparisonType::NOT_EQ> {
  24. template <typename T, class U>
  25. bool operator()(const T& first, const U& second) throw() {
  26. return first != second;
  27. }
  28. };
  29.  
  30. template<>
  31. struct Compare<EComparisonType::LESS> {
  32. template <typename T, class U>
  33. bool operator()(const T& first, const U& second) throw() {
  34. return first < second;
  35. }
  36. };
  37.  
  38. template<>
  39. struct Compare<EComparisonType::LESS_OR_EQ> {
  40. template <typename T, class U>
  41. bool operator()(const T& first, const U& second) throw() {
  42. return first <= second;
  43. }
  44. };
  45.  
  46. template<>
  47. struct Compare<EComparisonType::GREATER> {
  48. template <typename T, class U>
  49. bool operator()(const T& first, const U& second) throw() {
  50. return first > second;
  51. }
  52. };
  53.  
  54. template<>
  55. struct Compare<EComparisonType::GREATER_OR_EQ> {
  56. template <typename T, class U>
  57. bool operator()(const T& first, const U& second) throw() {
  58. return first >= second;
  59. }
  60. };
  61.  
  62. #include <cstddef>
  63. #include <cstdint>
  64. #include <type_traits>
  65.  
  66. // bool val. to bool type
  67. template <const bool Bool>
  68. struct BoolType {};
  69.  
  70. template<>
  71. struct BoolType<true> {
  72. typedef std::true_type Type;
  73. };
  74.  
  75. template<>
  76. struct BoolType<false> {
  77. typedef std::false_type Type;
  78. };
  79.  
  80. #define BOOL_TYPE(BoolVal) BoolType<BoolVal>::Type
  81.  
  82. // HINT: std::add_const / std::remove_const also can be used
  83. template <typename T, const bool Constant>
  84. struct AddRemoveConst {};
  85.  
  86. template <typename T>
  87. struct AddRemoveConst<T, true> {
  88. typedef const T Type;
  89. };
  90.  
  91. template <typename T>
  92. struct AddRemoveConst<T, false> {
  93. typedef T Type;
  94. };
  95.  
  96. #define ADD_REMOVE_CONST(Type, StaticPredicate) AddRemoveConst<Type, StaticPredicate>::Type
  97.  
  98. // std::is_fundamental [http://w...content-available-to-author-only...s.com/reference/type_traits/is_fundamental/]
  99. enum class ECFundamentalTypeTags {
  100. UNIDENTIFIED,
  101. BOOL,
  102. SIGNED_CHAR,
  103. UNSIGNED_CHAR,
  104. // Signedness of wchar_t is unspecified
  105. // [http://stackoverflow.com/questions/11953363/wchar-t-is-unsigned-or-signed]
  106. WCHAR,
  107.  
  108. //// 'char16_t' AND 'char32_t' SHOULD be a keywords since the C++11,
  109. //// BUT MS VS Community 2013 Upd 5 does NOT supports that
  110. //// AND specifys 'char16_t' AND 'char32_t' as a typdef aliases instead
  111. //// (so they are NOT presented here)
  112.  
  113. SIGNED_SHORT_INT,
  114. UNSIGNED_SHORT_INT,
  115. SIGNED_INT,
  116. UNSIGNED_INT,
  117. SIGNED_LONG_INT,
  118. UNSIGNED_LONG_INT,
  119. SIGNED_LONG_LONG_INT, // C++11
  120. UNSIGNED_LONG_LONG_INT, // C++11
  121. FLOAT,
  122. DOUBLE,
  123. LONG_DOUBLE,
  124. VOID_,
  125. NULLPTR // C++11 std::nullptr_t
  126. };
  127.  
  128. template <typename T, class TypeTags = ECFundamentalTypeTags>
  129. struct TypeTag {
  130. static const auto TAG = TypeTags::UNIDENTIFIED;
  131. };
  132.  
  133. template <class TypeTags>
  134. struct TypeTag<bool, TypeTags> {
  135. static const auto TAG = TypeTags::BOOL;
  136. };
  137.  
  138. template <class TypeTags>
  139. struct TypeTag<signed char, TypeTags> {
  140. static const auto TAG = TypeTags::SIGNED_CHAR;
  141. };
  142.  
  143. template <class TypeTags>
  144. struct TypeTag<unsigned char, TypeTags> {
  145. static const auto TAG = TypeTags::UNSIGNED_CHAR;
  146. };
  147.  
  148. template <class TypeTags>
  149. struct TypeTag<wchar_t, TypeTags> {
  150. static const auto TAG = TypeTags::WCHAR;
  151. };
  152.  
  153. template <class TypeTags>
  154. struct TypeTag<signed short int, TypeTags> {
  155. static const auto TAG = TypeTags::SIGNED_SHORT_INT;
  156. };
  157.  
  158. template <class TypeTags>
  159. struct TypeTag<unsigned short int, TypeTags> {
  160. static const auto TAG = TypeTags::UNSIGNED_SHORT_INT;
  161. };
  162.  
  163. template <class TypeTags>
  164. struct TypeTag<signed int, TypeTags> {
  165. static const auto TAG = TypeTags::SIGNED_INT;
  166. };
  167.  
  168. template <class TypeTags>
  169. struct TypeTag<unsigned int, TypeTags> {
  170. static const auto TAG = TypeTags::UNSIGNED_INT;
  171. };
  172.  
  173. template <class TypeTags>
  174. struct TypeTag<signed long int, TypeTags> {
  175. static const auto TAG = TypeTags::SIGNED_LONG_INT;
  176. };
  177.  
  178. template <class TypeTags>
  179. struct TypeTag<unsigned long int, TypeTags> {
  180. static const auto TAG = TypeTags::UNSIGNED_LONG_INT;
  181. };
  182.  
  183. template <class TypeTags>
  184. struct TypeTag<signed long long int, TypeTags> {
  185. static const auto TAG = TypeTags::SIGNED_LONG_LONG_INT;
  186. };
  187.  
  188. template <class TypeTags>
  189. struct TypeTag<unsigned long long int, TypeTags> {
  190. static const auto TAG = TypeTags::UNSIGNED_LONG_LONG_INT;
  191. };
  192.  
  193. template <class TypeTags>
  194. struct TypeTag<float, TypeTags> {
  195. static const auto TAG = TypeTags::FLOAT;
  196. };
  197.  
  198. template <class TypeTags>
  199. struct TypeTag<double, TypeTags> {
  200. static const auto TAG = TypeTags::DOUBLE;
  201. };
  202.  
  203. template <class TypeTags>
  204. struct TypeTag<long double, TypeTags> {
  205. static const auto TAG = TypeTags::LONG_DOUBLE;
  206. };
  207.  
  208. template <class TypeTags>
  209. struct TypeTag<void, TypeTags> {
  210. static const auto TAG = TypeTags::VOID_;
  211. };
  212.  
  213. template <class TypeTags>
  214. struct TypeTag<std::nullptr_t, TypeTags> {
  215. static const auto TAG = TypeTags::NULLPTR;
  216. };
  217.  
  218. #define TYPE_TAG(Object) TypeTag<std::decay<decltype(Object)>::type>::TAG
  219.  
  220. // Size is in bytes
  221. // Fixed width integer types (since C++11): http://e...content-available-to-author-only...e.com/w/cpp/types/integer
  222. // See also: http://w...content-available-to-author-only...4.com/en/t/0012/
  223. template <const size_t Size, const bool Signed>
  224. struct IntegralTypeBySize {
  225. static const auto TAG = ECFundamentalTypeTags::UNIDENTIFIED;
  226. };
  227.  
  228. template<>
  229. struct IntegralTypeBySize<1U, true> {
  230. typedef int8_t Type;
  231. static const auto TAG = TypeTag<Type, ECFundamentalTypeTags>::TAG;
  232. };
  233.  
  234. template<>
  235. struct IntegralTypeBySize<2U, true> {
  236. typedef int16_t Type;
  237. static const auto TAG = TypeTag<Type, ECFundamentalTypeTags>::TAG;
  238. };
  239.  
  240. template<>
  241. struct IntegralTypeBySize<4U, true> {
  242. typedef int32_t Type;
  243. static const auto TAG = TypeTag<Type, ECFundamentalTypeTags>::TAG;
  244. };
  245.  
  246. template<>
  247. struct IntegralTypeBySize<8U, true> {
  248. typedef int64_t Type;
  249. static const auto TAG = TypeTag<Type, ECFundamentalTypeTags>::TAG;
  250. };
  251.  
  252. template<>
  253. struct IntegralTypeBySize<1U, false> {
  254. typedef uint8_t Type;
  255. static const auto TAG = TypeTag<Type, ECFundamentalTypeTags>::TAG;
  256. };
  257.  
  258. template<>
  259. struct IntegralTypeBySize<2U, false> {
  260. typedef uint16_t Type;
  261. static const auto TAG = TypeTag<Type, ECFundamentalTypeTags>::TAG;
  262. };
  263.  
  264. template<>
  265. struct IntegralTypeBySize<4U, false> {
  266. typedef uint32_t Type;
  267. static const auto TAG = TypeTag<Type, ECFundamentalTypeTags>::TAG;
  268. };
  269.  
  270. template<>
  271. struct IntegralTypeBySize<8U, false> {
  272. typedef uint64_t Type;
  273. static const auto TAG = TypeTag<Type, ECFundamentalTypeTags>::TAG;
  274. };
  275.  
  276. //// Random Access Iterator [http://e...content-available-to-author-only...e.com/w/cpp/concept/RandomAccessIterator]
  277.  
  278. #include <limits>
  279. #include <iterator>
  280.  
  281. // [!] Do NOT change an order of the elements NOR alter the sequence
  282. // coze it may break an internal comparison logic [!]
  283. enum EIterPosType {
  284. IPT_BEFORE_BEGIN,
  285. IPT_BEFORE_REVERSED_BEGIN,
  286. IPT_NORMAL,
  287. IPT_PAST_THE_END,
  288. IPT_PAST_THE_REVERSED_END
  289. };
  290.  
  291. //// Key features:
  292. //// 1) functionality (bidirectional + random access)
  293. //// 2) safety (the ONLY way to invalidate an iterator is to destroy the related container object)
  294. //// 3) versatility (CAN provide mutable/read-only access AND switch direction/container at the real time)
  295. //// 4) commonality (CAN be used with the multiple container types which satisfies the requirements)
  296. //// [!] PERFORMANCE WARNING: for efficient use,
  297. //// related container SHOULD provide fast access to the ANY item by its idx. [!]
  298. //// Traits:
  299. //// 1) dereferenceable
  300. //// (even in 'past-the-end', 'before-begin' OR singular/invalidated state,
  301. //// returning ref. to the mock obj. in those cases)
  302. //// 2) incrementable
  303. //// 3) swappable: meet the requirements of 'MoveAssignable' and 'MoveConstructible'
  304. //// (http://e...content-available-to-author-only...e.com/w/cpp/concept/Swappable,
  305. //// http://e...content-available-to-author-only...e.com/w/cpp/algorithm/swap)
  306.  
  307. // 'TContainerType' should support the following properties, fileds AND methods:
  308. // 'value_type', 'operator[]()', 'size()', 'empty()'
  309. template <typename TContainerType, class TContainerElemType,
  310. const bool Reversed = false, const bool Constant = true>
  311. // C++ iterator concept: http://e...content-available-to-author-only...e.com/w/cpp/concept/Iterator
  312. // Random-access iterators are iterators that can be used to access (AND modify if 'Constant' is false)
  313. // elements at an arbitrary offset position relative to the element they point to,
  314. // offering the same functionality as pointers (to constants if 'Constant' is true)
  315. // [!] Does NOT thread safe (BUT satisfy BASIC STL thread safety guarantee:
  316. // http://e...content-available-to-author-only...e.com/w/cpp/container#Iterator_invalidation) [!]
  317. class GenericRAIterator : public std::iterator<std::random_access_iterator_tag, TContainerElemType> {
  318.  
  319. public:
  320. //// From the base class
  321. typedef typename std::iterator<std::random_access_iterator_tag, TContainerElemType>::value_type value_type;
  322. typedef typename std::iterator<std::random_access_iterator_tag, TContainerElemType>::difference_type difference_type;
  323.  
  324. typedef typename BOOL_TYPE(Constant) TConstantnessType;
  325.  
  326. static const auto CONSTANT = Constant;
  327. static const size_t MAX_HANDLED_ELEMS;
  328.  
  329. //// Use 'Constant' to make iterator type mutable (switch work mode from input to input-output)
  330. typedef typename AddRemoveConst<TContainerType, Constant>::Type TMutableContainerType;
  331. typedef typename AddRemoveConst<value_type, Constant>::Type TMutableValueType;
  332.  
  333. typedef typename std::iterator<std::random_access_iterator_tag, value_type> TBaseIterType;
  334.  
  335. // Creates a 'begin' OR 'rbegin' (see here: http://e...content-available-to-author-only...e.com/w/cpp/container/vector/rbegin)
  336. // linked OR unliked iterator
  337. GenericRAIterator(TMutableContainerType* const container = nullptr,
  338. const bool reversed = Reversed) throw()
  339. : reversed_(reversed)
  340. {
  341. linkToTheContainer(container); // alseo sets pos.
  342. }
  343.  
  344. //// [!] Move constructor AND move operator will be ALSO auto. generated by the compiler
  345. //// AND will behaves like it's 'copy' equivalents [!]
  346. //// TO DO: allow to construct (AND assign) constant iter. from the NONE constant one
  347. GenericRAIterator(const GenericRAIterator&) = default;
  348. GenericRAIterator& operator=(const GenericRAIterator&) = default;
  349.  
  350. ~GenericRAIterator() throw() {
  351. linkToTheContainer(); // unlink
  352. }
  353.  
  354. //// 'at', 'operator*', 'operator->' AND 'operator[]'
  355. //// returns ref. (ptr) to the mock element in case of ERROR
  356. TMutableValueType& operator*() const throw() {
  357. return at(pos()); // curr. pos
  358. }
  359.  
  360. TMutableValueType* operator->() const throw() {
  361. return std::addressof(operator*());
  362. }
  363.  
  364. TMutableValueType& operator[](const difference_type idx) const throw() {
  365. return at(getShiftedPos(idx)); // shift to the curr. pos
  366. }
  367.  
  368. GenericRAIterator& operator++() throw() {
  369. return (*this += 1); // invoke operator+=''
  370. }
  371.  
  372. GenericRAIterator operator++(const int) throw() {
  373. GenericRAIterator copy(*this);
  374. operator++();
  375. return std::move(copy);
  376. }
  377.  
  378. GenericRAIterator& operator--() throw() {
  379. return (*this -= 1); // 'invoke operator-='
  380. }
  381.  
  382. GenericRAIterator operator--(const int) throw() {
  383. GenericRAIterator copy(*this);
  384. operator--();
  385. return std::move(copy);
  386. }
  387.  
  388. //// 'shift' can be both positive or negative; the complexity SHOULD be constant
  389.  
  390. GenericRAIterator& operator+=(const difference_type shift) throw() {
  391. setPos(getShiftedPos(shift)); // updated pos.
  392. return *this;
  393. }
  394.  
  395. GenericRAIterator& operator-=(const difference_type shift) throw() {
  396. return (*this += -shift); // exec. 'operator+=()'
  397. }
  398.  
  399. EIterPosType posType() const throw() {
  400. static_assert(EIterPosType::IPT_BEFORE_BEGIN < EIterPosType::IPT_NORMAL &&
  401. EIterPosType::IPT_NORMAL < EIterPosType::IPT_PAST_THE_END,
  402. "Incorrect 'EIterPosType' values order");
  403.  
  404. if (pos() < 0) return reversed() ? EIterPosType::IPT_PAST_THE_REVERSED_END
  405. : EIterPosType::IPT_BEFORE_BEGIN;
  406. #pragma warning(disable: 4018) // signed/unsigned mismatch: 'pos() >= container()->size()'
  407. if (pos() >= container()->size()) return reversed() ? EIterPosType::IPT_BEFORE_REVERSED_BEGIN
  408. : EIterPosType::IPT_PAST_THE_END;
  409. #pragma warning(default: 4018)
  410. return EIterPosType::IPT_NORMAL;
  411. }
  412.  
  413. //// Note that for the types that are both 'EqualityComparable' AND 'LessThanComparable',
  414. //// the C++ standard library makes a distinction between
  415. //// 'equality', which is the value of the expression 'a == b' AND
  416. //// 'equivalence', which is the value of the expression '!(a < b) && !(b < a)'
  417.  
  418. template <const bool OtherReversed, const bool OtherConstant, const EComparisonType ComparisonType>
  419. bool compare(const GenericRAIterator<TContainerType, value_type, OtherReversed, OtherConstant>& iter,
  420. const bool checkType = false) const throw()
  421. {
  422. // constexpr ('returnValBasedOnEq' AND 'isEq')??
  423. auto returnValBasedOnEq = [&](const bool isEq) throw() { // ONLY if SHOULD NOT do actual compare
  424. switch (ComparisonType) {
  425. case EComparisonType::EQ:
  426. case EComparisonType::LESS_OR_EQ:
  427. case EComparisonType::GREATER_OR_EQ:
  428. return isEq;
  429.  
  430. case EComparisonType::LESS:
  431. case EComparisonType::GREATER:
  432. return false;
  433. }
  434. return !isEq; // '!='
  435. };
  436.  
  437. if (this == &iter) return returnValBasedOnEq(true); // same instance
  438.  
  439. // Diff. type iters are diff. even if they linked to the same sequence [CAN NOT be comparable]
  440. if (checkType && reversed() != iter.reversed()) return returnValBasedOnEq(false);
  441.  
  442. if (container() != iter.container())
  443. return returnValBasedOnEq(false); // diff. containers (diff. domains)
  444. if (!container()) return returnValBasedOnEq(true); // both a NONE-iterators (unlinked)
  445.  
  446. // 'std::vector::end' - if the container is empty, this function returns the same as vector::begin
  447. // For an empty container 'begin' == 'end' AND so let the 'rbegin' == 'rend'
  448. // AND ALL other iters are the same
  449. if (container()->empty()) return returnValBasedOnEq(true);
  450.  
  451. const auto thisPosType = posType();
  452. if (EIterPosType::IPT_NORMAL == thisPosType) {
  453. auto thisPos = pos(), otherPos = iter.pos();
  454. if (reversed()) std::swap(thisPos, otherPos);
  455. return Compare<ComparisonType>()(thisPos, otherPos); // comparing absolute pos.
  456. }
  457. // Past-the-end OR before-begin: comparing relative pos.
  458. return Compare<ComparisonType>()(thisPosType, iter.posType());
  459. }
  460.  
  461. template <const bool OtherReversed, const bool OtherConstant>
  462. bool operator==(const GenericRAIterator<TContainerType, value_type,
  463. OtherReversed, OtherConstant>& iter) const throw() {
  464. return compare<OtherReversed, OtherConstant, EComparisonType::EQ>(iter);
  465. }
  466.  
  467. template <const bool OtherReversed, const bool OtherConstant>
  468. bool operator!=(const GenericRAIterator<TContainerType, value_type,
  469. OtherReversed, OtherConstant>& iter) const throw() {
  470. return !(*this == iter); // invoke 'operator==(const GenericRAIterator&)'
  471. }
  472.  
  473. template <const bool OtherReversed, const bool OtherConstant>
  474. bool operator<(const GenericRAIterator<TContainerType, value_type,
  475. OtherReversed, OtherConstant>& iter) const throw() {
  476. return compare<OtherReversed, OtherConstant, EComparisonType::LESS>(iter);
  477. }
  478.  
  479. template <const bool OtherReversed, const bool OtherConstant>
  480. bool operator>(const GenericRAIterator<TContainerType, value_type,
  481. OtherReversed, OtherConstant>& iter) const throw() {
  482. return compare<OtherReversed, OtherConstant, EComparisonType::GREATER>(iter);
  483. }
  484.  
  485. template <const bool OtherReversed, const bool OtherConstant>
  486. bool operator<=(const GenericRAIterator<TContainerType, value_type,
  487. OtherReversed, OtherConstant>& iter) const throw() {
  488. return compare<OtherReversed, OtherConstant, EComparisonType::LESS_OR_EQ>(iter);
  489. }
  490.  
  491. template <const bool OtherReversed, const bool OtherConstant>
  492. bool operator>=(const GenericRAIterator<TContainerType, value_type,
  493. OtherReversed, OtherConstant>& iter) const throw() {
  494. return compare<OtherReversed, OtherConstant, EComparisonType::GREATER_OR_EQ>(iter);
  495. }
  496.  
  497. // Resets pos.: moves pos. to the 'begin' OR 'rbegin'
  498. // (OR 'past-the-end' - if empty) based on the iter. type
  499. void reset() throw() {
  500. if (container()) { // if linked
  501. if (reversed()) { // end -> begin
  502. const auto size = container()->size();
  503. // 'rbegin' OR past-the-end (if empty) [http://w...content-available-to-author-only...s.com/reference/vector/vector/rbegin/]
  504. setPos(size ? size - 1 : 0);
  505. } else {
  506. // 'begin' OR past-the-end (if empty) [http://w...content-available-to-author-only...s.com/reference/vector/vector/begin/]
  507. setPos();
  508. }
  509. } else setPos(); // unlinked
  510. }
  511.  
  512. // Resets iter. AND removes the reversion (if reversed)
  513. void clear() throw() {
  514. reset();
  515. if (reversed()) reverse(); // make unreversed
  516. }
  517.  
  518. // Called with NO data provided will partially invalidate the iterator -
  519. // partially invalid iterator will be left in the valid, BUT unlinked state
  520. // Also resets pos.
  521. void linkToTheContainer(TMutableContainerType* const container = nullptr) throw() {
  522. setContainer(container);
  523. reset();
  524. }
  525.  
  526. // Returns false if unlinked
  527. // Despite it's name, the func. can NOT 100% gurantee the instance is surely valid
  528. // (the linked container CAN be already destroyed)
  529. bool valid() const throw() {
  530. return (nullptr != container()); // false if unlinked
  531. }
  532.  
  533. bool dereferencable() const throw() {
  534. if (!valid()) return false; // invalid
  535. #pragma warning(disable: 4018) // signed/unsigned mismatch: 'pos() < container()->size()'
  536. // Valid pos. (NOT 'past-the-end' NOR 'before-begin')
  537. return ((pos() > -1) && (pos() < container()->size()));
  538. #pragma warning(default: 4018)
  539. }
  540.  
  541. private:
  542.  
  543. //// 'ErrMsg' mutable member was removed in order to satisfy STL thread safety standart,
  544. //// which says that 'all const member functions can be called concurrently by different
  545. //// threads on the same object, more generally, the C++ standard library functions
  546. //// do not modify objects unless those objects are accessible, directly or indirectly'
  547.  
  548. bool reversed_ = Reversed;
  549. difference_type pos__ = difference_type(); // absolute pos. [-1, container_->size()]
  550. TMutableContainerType* container_ = nullptr;
  551.  
  552. public:
  553.  
  554. TMutableValueType& at(const decltype(pos__) pos) const throw() {
  555. static TMutableValueType DUMMY = TMutableValueType(); // will be zeroised (default created) as a static
  556.  
  557. if (container()) {
  558. #pragma warning(disable: 4018) // signed/unsigned mismatch: 'pos > containerPtr->size()'
  559. if (pos < 0 || pos > container()->size()) {
  560. return DUMMY; // attempt to dereference a before-begin OR past-the-end iterato
  561. }
  562. #pragma warning(default: 4018)
  563. return (*container())[pos];
  564. }
  565. return DUMMY; // attempt to dereference an unlinked (singular) iterator
  566. }
  567.  
  568. void reverse() throw() {
  569. reversed_ = !reversed_;
  570. }
  571.  
  572. auto reversed() const throw() -> decltype(reversed_) {
  573. return reversed_;
  574. }
  575.  
  576. // If pos. after the last elem.: 'past-the-end'; if before first: 'before-begin'
  577. // If the related container is empty -
  578. // ALL 'past-the-end' AND 'before-begin' iterators are considered equal
  579. // (pointing to the no-element)
  580. // Given some none-empty container with last elem idx. is '2' (for example),
  581. // ANY 'past-the-end' iterators linked to this conainer
  582. // are considered equal, regardless of their actual pos. - 3, 5 OR 1000 etc.
  583. // (same logic for the 'before-begin' iterators: -1, -7, -300 iterators are considered equal)
  584. auto pos() const throw() -> decltype(pos__) {
  585. return pos__;
  586. }
  587.  
  588. auto container() const throw() -> decltype(container_) {
  589. return container_;
  590. }
  591.  
  592. private:
  593.  
  594. void setPos(const decltype(pos__) pos = 0) throw() {
  595. pos__ = pos;
  596. }
  597.  
  598. void setContainer(decltype(container_) const container = nullptr) throw() {
  599. container_ = container;
  600. }
  601.  
  602. auto getShiftedPos(const difference_type shift = 0U) const throw() -> decltype(pos__) {
  603. return pos__ + (reversed_ ? -shift : shift);
  604. }
  605. };
  606.  
  607. template <typename TContainerType, class TContainerElemType,
  608. const bool Reversed, const bool Constant>
  609. const size_t
  610. GenericRAIterator<TContainerType, TContainerElemType, Reversed, Constant>::MAX_HANDLED_ELEMS
  611. = std::numeric_limits<decltype(pos__)>::max() + 1U;
  612.  
  613. template <typename TContainerType, class TContainerElemType,
  614. const bool Reversed, const bool Constant>
  615. GenericRAIterator<TContainerType, TContainerElemType, Reversed, Constant>
  616. operator+(const GenericRAIterator<TContainerType, TContainerElemType,
  617. Reversed, Constant>& iter,
  618. typename GenericRAIterator<TContainerType, TContainerElemType,
  619. Reversed, Constant>::difference_type const shift) throw()
  620. {
  621. auto copy(iter);
  622. copy += shift;
  623. return std::move(copy);
  624. }
  625.  
  626. template <typename TContainerType, class TContainerElemType,
  627. const bool Reversed, const bool Constant>
  628. GenericRAIterator<TContainerType, TContainerElemType, Reversed, Constant>
  629. operator+(typename GenericRAIterator<TContainerType, TContainerElemType,
  630. Reversed, Constant>::difference_type const shift,
  631. const GenericRAIterator<TContainerType, TContainerElemType,
  632. Reversed, Constant>& iter) throw()
  633. {
  634. return std::move(iter + shift); // exec. 'operator+(iter_type, diff_type)'
  635. }
  636.  
  637. template <typename TContainerType, class TContainerElemType,
  638. const bool Reversed, const bool Constant>
  639. GenericRAIterator<TContainerType, TContainerElemType, Reversed, Constant>
  640. operator-(const GenericRAIterator<TContainerType, TContainerElemType,
  641. Reversed, Constant>& iter,
  642. typename GenericRAIterator<TContainerType, TContainerElemType,
  643. Reversed, Constant>::difference_type const shift) throw()
  644. {
  645. return std::move(iter + (-shift)); // exec. 'operator+(iter_type, diff_type)'
  646. }
  647.  
  648. // Retruns max. value if diff. domain
  649. // Precondition: a + n == b; Postcondition: b == a + (b - a)
  650. template <typename TContainerType, class TContainerElemType,
  651. const bool Reversed, const bool Constant1, const bool Constant2>
  652. auto operator-(const GenericRAIterator<TContainerType, TContainerElemType,
  653. Reversed, Constant1>& iter1,
  654. const GenericRAIterator<TContainerType, TContainerElemType,
  655. Reversed, Constant2>& iter2) throw()
  656. -> typename GenericRAIterator<TContainerType, TContainerElemType,
  657. Reversed, Constant1>::difference_type
  658. {
  659. typedef typename GenericRAIterator<TContainerType, TContainerElemType,
  660. Reversed, Constant1>::difference_type difference_type;
  661. // If diff. domain
  662. if (iter1.container() != iter2.container()) return std::numeric_limits<difference_type>::max();
  663. return (iter1.pos() - iter2.pos());
  664. }
  665.  
  666. #include <cstring>
  667. #include <iostream>
  668.  
  669. int main() {
  670. struct MyStr {
  671. MyStr(const char* str) throw() {
  672. if(str) {
  673. strcpy(buf, str);
  674. len = strlen(buf);
  675. }
  676. }
  677.  
  678. char& operator[](const size_t idx) throw() {
  679. static char C = '\0';
  680. return idx >= len ? C : buf[idx];
  681. }
  682.  
  683. const char& operator[](const size_t idx) const throw() {
  684. static const char C = '\0';
  685. return idx >= len ? C : buf[idx];
  686. }
  687.  
  688. size_t size() const throw() {
  689. return len;
  690. }
  691.  
  692. bool empty() const throw() {
  693. return !len;
  694. }
  695.  
  696. size_t len = 0U;
  697.  
  698. typedef char value_type;
  699. value_type buf[256U];
  700.  
  701. typedef GenericRAIterator<MyStr, value_type, false, true> const_iterator;
  702. typedef GenericRAIterator<MyStr, value_type, true, true> const_reverse_iterator;
  703.  
  704. const_iterator begin() const throw() {
  705. return std::move(const_iterator(this));
  706. }
  707.  
  708. const_iterator end() const throw() {
  709. const_iterator iter(this);
  710. return std::move(iter += size()); // to past-the-end pos.
  711. }
  712.  
  713. const_reverse_iterator rbegin() const throw() {
  714. return std::move(const_reverse_iterator(this, true));
  715. }
  716.  
  717. const_reverse_iterator rend() const throw() {
  718. const_reverse_iterator iter(this, true);
  719. return std::move(iter += size()); // to before-begin pos.
  720. }
  721. } myStr = "we don't need no water!";
  722.  
  723. for(const auto c : myStr) {
  724. std::cout << c;
  725. }
  726. std::cout << std::endl;
  727.  
  728. auto iter = myStr.rbegin();
  729. const auto end = myStr.rend();
  730. for(; iter != end; ++iter) {
  731. std::cout << *iter;
  732. }
  733. return 0;
  734. }
Success #stdin #stdout 0s 3456KB
stdin
Standard input is empty
stdout
we don't need no water!
!retaw on deen t'nod ew