IteratorsTest.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /*
  2. * Copyright 2016-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <map>
  17. #include <folly/container/Array.h>
  18. #include <folly/detail/Iterators.h>
  19. #include <folly/portability/GTest.h>
  20. using namespace folly::detail;
  21. using namespace folly;
  22. namespace {
  23. struct IntArrayIterator : IteratorFacade<IntArrayIterator, int const> {
  24. explicit IntArrayIterator(int const* a) : a_(a) {}
  25. void increment() {
  26. ++a_;
  27. }
  28. int const& dereference() const {
  29. return *a_;
  30. }
  31. bool equal(IntArrayIterator const& rhs) const {
  32. return rhs.a_ == a_;
  33. }
  34. int const* a_;
  35. };
  36. } // namespace
  37. TEST(IteratorsTest, IterFacadeHasCorrectTraits) {
  38. using TR = std::iterator_traits<IntArrayIterator>;
  39. static_assert(std::is_same<TR::value_type, int const>::value, "");
  40. static_assert(std::is_same<TR::reference, int const&>::value, "");
  41. static_assert(std::is_same<TR::pointer, int const*>::value, "");
  42. static_assert(
  43. std::is_same<TR::iterator_category, std::forward_iterator_tag>::value,
  44. "");
  45. static_assert(std::is_same<TR::difference_type, ssize_t>::value, "");
  46. }
  47. TEST(IteratorsTest, SimpleIteratorFacade) {
  48. static const auto kArray = folly::make_array(42, 43, 44);
  49. IntArrayIterator end(kArray.data() + kArray.size());
  50. IntArrayIterator iter(kArray.data());
  51. EXPECT_NE(iter, end);
  52. EXPECT_EQ(42, *iter);
  53. ++iter;
  54. EXPECT_NE(iter, end);
  55. EXPECT_EQ(43, *iter);
  56. ++iter;
  57. EXPECT_NE(iter, end);
  58. EXPECT_EQ(44, *iter);
  59. ++iter;
  60. EXPECT_EQ(iter, end);
  61. }
  62. namespace {
  63. // Simple iterator adaptor: wraps an int pointer.
  64. struct IntPointerIter : IteratorAdaptor<IntPointerIter, int const*, int const> {
  65. using Super = IteratorAdaptor<IntPointerIter, int const*, int const>;
  66. explicit IntPointerIter(int const* ptr) : Super(ptr) {}
  67. };
  68. } // namespace
  69. TEST(IteratorsTest, IterAdaptorHasCorrectTraits) {
  70. using TR = std::iterator_traits<IntPointerIter>;
  71. static_assert(std::is_same<TR::value_type, int const>::value, "");
  72. static_assert(std::is_same<TR::reference, int const&>::value, "");
  73. static_assert(std::is_same<TR::pointer, int const*>::value, "");
  74. static_assert(
  75. std::is_same<TR::iterator_category, std::forward_iterator_tag>::value,
  76. "");
  77. static_assert(std::is_same<TR::difference_type, ssize_t>::value, "");
  78. }
  79. TEST(IteratorsTest, IterAdaptorWithPointer) {
  80. static const auto kArray = folly::make_array(42, 43, 44);
  81. IntPointerIter end(kArray.data() + kArray.size());
  82. IntPointerIter iter(kArray.data());
  83. EXPECT_NE(iter, end);
  84. EXPECT_EQ(42, *iter);
  85. ++iter;
  86. EXPECT_NE(iter, end);
  87. EXPECT_EQ(43, *iter);
  88. ++iter;
  89. EXPECT_NE(iter, end);
  90. EXPECT_EQ(44, *iter);
  91. ++iter;
  92. EXPECT_EQ(iter, end);
  93. }
  94. namespace {
  95. // More complex case: wrap a map iterator, but these provide either the key or
  96. // value.
  97. struct IntMapKeyIter
  98. : IteratorAdaptor<IntMapKeyIter, std::map<int, int>::iterator, int const> {
  99. using Super =
  100. IteratorAdaptor<IntMapKeyIter, std::map<int, int>::iterator, int const>;
  101. explicit IntMapKeyIter(std::map<int, int>::iterator iter) : Super(iter) {}
  102. int const& dereference() const {
  103. return base()->first;
  104. }
  105. };
  106. struct IntMapValueIter
  107. : IteratorAdaptor<IntMapValueIter, std::map<int, int>::iterator, int> {
  108. using Super =
  109. IteratorAdaptor<IntMapValueIter, std::map<int, int>::iterator, int>;
  110. explicit IntMapValueIter(std::map<int, int>::iterator iter) : Super(iter) {}
  111. int& dereference() const {
  112. return base()->second;
  113. }
  114. };
  115. } // namespace
  116. TEST(IteratorsTest, IterAdaptorOfOtherIter) {
  117. std::map<int, int> m{{2, 42}, {3, 43}, {4, 44}};
  118. IntMapKeyIter keyEnd(m.end());
  119. IntMapKeyIter keyIter(m.begin());
  120. EXPECT_NE(keyIter, keyEnd);
  121. EXPECT_EQ(2, *keyIter);
  122. ++keyIter;
  123. EXPECT_NE(keyIter, keyEnd);
  124. EXPECT_EQ(3, *keyIter);
  125. ++keyIter;
  126. EXPECT_NE(keyIter, keyEnd);
  127. EXPECT_EQ(4, *keyIter);
  128. ++keyIter;
  129. EXPECT_EQ(keyIter, keyEnd);
  130. IntMapValueIter valueEnd(m.end());
  131. IntMapValueIter valueIter(m.begin());
  132. EXPECT_NE(valueIter, valueEnd);
  133. EXPECT_EQ(42, *valueIter);
  134. ++valueIter;
  135. EXPECT_NE(valueIter, valueEnd);
  136. EXPECT_EQ(43, *valueIter);
  137. ++valueIter;
  138. EXPECT_NE(valueIter, valueEnd);
  139. EXPECT_EQ(44, *valueIter);
  140. ++valueIter;
  141. EXPECT_EQ(valueIter, valueEnd);
  142. }
  143. namespace {
  144. struct IntMapValueIterConst : IteratorAdaptor<
  145. IntMapValueIterConst,
  146. std::map<int, int>::const_iterator,
  147. int const> {
  148. using Super = IteratorAdaptor<
  149. IntMapValueIterConst,
  150. std::map<int, int>::const_iterator,
  151. int const>;
  152. explicit IntMapValueIterConst(std::map<int, int>::const_iterator iter)
  153. : Super(iter) {}
  154. /* implicit */ IntMapValueIterConst(IntMapValueIter const& rhs)
  155. : IntMapValueIterConst(rhs.base()) {}
  156. int const& dereference() const {
  157. return base()->second;
  158. }
  159. };
  160. } // namespace
  161. TEST(IteratorsTest, MixedConstAndNonconstIters) {
  162. std::map<int, int> m{{2, 42}, {3, 43}, {4, 44}};
  163. IntMapValueIterConst cend(m.cend());
  164. IntMapValueIter valueIter(m.begin());
  165. EXPECT_NE(valueIter, cend);
  166. ++valueIter;
  167. ++valueIter;
  168. ++valueIter;
  169. EXPECT_EQ(valueIter, cend);
  170. }