aboutsummaryrefslogtreecommitdiff
path: root/EASTL/test/source/TestIterator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'EASTL/test/source/TestIterator.cpp')
-rw-r--r--EASTL/test/source/TestIterator.cpp192
1 files changed, 185 insertions, 7 deletions
diff --git a/EASTL/test/source/TestIterator.cpp b/EASTL/test/source/TestIterator.cpp
index e168118..b6c6f76 100644
--- a/EASTL/test/source/TestIterator.cpp
+++ b/EASTL/test/source/TestIterator.cpp
@@ -4,6 +4,7 @@
#include "EASTLTest.h"
+#include <EASTL/deque.h>
#include <EASTL/iterator.h>
#include <EASTL/vector.h>
#include <EASTL/set.h>
@@ -14,12 +15,15 @@
#include <EASTL/string.h>
#include <EASTL/intrusive_list.h>
#include <EASTL/memory.h>
+#include <EASTL/unique_ptr.h>
EA_DISABLE_ALL_VC_WARNINGS()
#include <stdio.h>
#include <string.h>
EA_RESTORE_ALL_VC_WARNINGS()
+template <class T>
+using detect_iterator_traits_reference = typename eastl::iterator_traits<T>::reference;
// This is used below, though is currently disabled as documented below.
struct IListNode : public eastl::intrusive_list_node{};
@@ -139,6 +143,77 @@ int TestIterator_moveIterator()
EATEST_VERIFY(*moveIter != *(constBeginMoveIter + 2));
}
+ {
+ // Ensure that move_iterator indeed move yielded value whenever possible.
+ auto x = eastl::make_unique<int>(42);
+ auto* pX = &x;
+ auto moveIter = eastl::make_move_iterator(pX);
+
+ constexpr bool isCorrectReferenceType = eastl::is_same_v<decltype(moveIter)::reference, eastl::unique_ptr<int>&&>;
+ constexpr bool isCorrectReturnType = eastl::is_same_v<decltype(*moveIter), eastl::unique_ptr<int>&&>;
+
+ static_assert(isCorrectReferenceType, "move_iterator::reference has wrong type.");
+ static_assert(isCorrectReturnType, "move_iterator::operator*() has wrong return type.");
+ EATEST_VERIFY(isCorrectReferenceType);
+ EATEST_VERIFY(isCorrectReturnType);
+
+ auto pMoveX = *moveIter;
+ EATEST_VERIFY(*pMoveX == 42);
+ }
+
+ // Bellow are regression tests that ensure we are covering the defect LWG 2106: http://cplusplus.github.io/LWG/lwg-defects.html#2106
+ {
+ // Check that we support iterators yielding const references.
+ const int x = 42;
+ const int* pX = &x;
+ auto moveIter = eastl::make_move_iterator(pX);
+
+ constexpr bool isCorrectReferenceType = eastl::is_same_v<decltype(moveIter)::reference, const int&&>;
+ constexpr bool isCorrectReturnType = eastl::is_same_v<decltype(*moveIter), const int&&>;
+
+ static_assert(isCorrectReferenceType, "move_iterator::reference has wrong type.");
+ static_assert(isCorrectReturnType, "move_iterator::operator*() has wrong return type.");
+ EATEST_VERIFY(isCorrectReferenceType);
+ EATEST_VERIFY(isCorrectReturnType);
+
+ auto pCopiedX = *moveIter;
+ EATEST_VERIFY(pCopiedX == 42);
+ }
+
+ {
+ // Check that we support iterators yielding plain value (typically a proxy-iterator).
+ struct FakeProxyIterator
+ {
+ using iterator_category = EASTL_ITC_NS::forward_iterator_tag;
+ using difference_type = ptrdiff_t;
+ using value_type = int;
+ using pointer = int; // Note that we are yielding by value.
+ using reference = int; // Note that we are yielding by value.
+
+ reference operator*() const { return 42; }
+ pointer operator->() { return 42; }
+ FakeProxyIterator& operator++() { return *this; }
+ FakeProxyIterator operator++(int) { return {}; }
+
+ bool operator==(const FakeProxyIterator& rhs) { return true; };
+ bool operator!=(const FakeProxyIterator& rhs) { return false; };
+ };
+
+ FakeProxyIterator it = {};
+ auto moveIter = eastl::make_move_iterator(it);
+
+ constexpr bool isCorrectReferenceType = eastl::is_same_v<decltype(moveIter)::reference, int>;
+ constexpr bool isCorrectReturnType = eastl::is_same_v<decltype(*moveIter), int>;
+
+ static_assert(isCorrectReferenceType, "move_iterator::reference has wrong type.");
+ static_assert(isCorrectReturnType, "move_iterator::operator*() has wrong return type.");
+ EATEST_VERIFY(isCorrectReferenceType);
+ EATEST_VERIFY(isCorrectReturnType);
+
+ auto pCopiedX = *moveIter;
+ EATEST_VERIFY(pCopiedX == 42);
+ }
+
return nErrorCount;
}
@@ -178,6 +253,34 @@ int TestIterator()
}
{
+ // Regression bug with assign/insert combined with reverse iterator.
+ eastl::vector<int> a;
+ for (int i = 0; i < 10; ++i) {
+ a.push_back(i);
+ }
+
+ eastl::deque<int> d;
+ d.assign(a.rbegin(), a.rend());
+ for (int i = 0; i < 10; ++i) {
+ EATEST_VERIFY(a[i] == d[a.size() - i - 1]);
+ }
+ d.insert(d.end(), a.rbegin(), a.rend());
+ for (int i = 0; i < 10; ++i) {
+ EATEST_VERIFY(a[i] == d[d.size() - i - 1]);
+ }
+
+ eastl::vector<int> b;
+ b.assign(a.rbegin(), a.rend());
+ for (int i = 0; i < 10; ++i) {
+ EATEST_VERIFY(a[i] == b[a.size() - i - 1]);
+ }
+ b.insert(b.end(), a.rbegin(), a.rend());
+ for (int i = 0; i < 10; ++i) {
+ EATEST_VERIFY(a[i] == b[b.size() - i - 1]);
+ }
+ }
+
+ {
// move_iterator
// move_iterator<Iterator> make_move_iterator(Iterator mi)
typedef eastl::vector<eastl::string> StringArray;
@@ -349,13 +452,17 @@ int TestIterator()
{
// is_iterator_wrapper
- static_assert((eastl::is_iterator_wrapper<void>::value == false), "is_iterator_wrapper failure");
- static_assert((eastl::is_iterator_wrapper<int>::value == false), "is_iterator_wrapper failure");
- static_assert((eastl::is_iterator_wrapper<int*>::value == false), "is_iterator_wrapper failure");
- static_assert((eastl::is_iterator_wrapper<eastl::array<char>*>::value == false), "is_iterator_wrapper failure");
- static_assert((eastl::is_iterator_wrapper<eastl::vector<char> >::value == false), "is_iterator_wrapper failure");
- static_assert((eastl::is_iterator_wrapper<eastl::generic_iterator<int*> >::value == true), "is_iterator_wrapper failure");
- static_assert((eastl::is_iterator_wrapper<eastl::move_iterator<eastl::array<int>::iterator> >::value == true), "is_iterator_wrapper failure");
+ static_assert((eastl::is_iterator_wrapper<void>::value == false), "is_iterator_wrapper failure");
+ static_assert((eastl::is_iterator_wrapper<int>::value == false), "is_iterator_wrapper failure");
+ static_assert((eastl::is_iterator_wrapper<int*>::value == false), "is_iterator_wrapper failure");
+ static_assert((eastl::is_iterator_wrapper<eastl::array<int>::iterator>::value == false), "is_iterator_wrapper failure");
+ static_assert((eastl::is_iterator_wrapper<eastl::array<char>*>::value == false), "is_iterator_wrapper failure");
+ static_assert((eastl::is_iterator_wrapper<eastl::vector<char> >::value == false), "is_iterator_wrapper failure");
+ static_assert((eastl::is_iterator_wrapper<eastl::generic_iterator<int*> >::value == true), "is_iterator_wrapper failure");
+ static_assert((eastl::is_iterator_wrapper<eastl::move_iterator<eastl::array<int>::iterator> >::value == true), "is_iterator_wrapper failure");
+ static_assert((eastl::is_iterator_wrapper<eastl::reverse_iterator<eastl::array<int>::iterator> >::value == false), "is_iterator_wrapper failure");
+ static_assert((eastl::is_iterator_wrapper<eastl::reverse_iterator<int*> >::value == false), "is_iterator_wrapper failure");
+ static_assert((eastl::is_iterator_wrapper<eastl::reverse_iterator<eastl::move_iterator<int*>> >::value == true), "is_iterator_wrapper failure");
}
@@ -383,6 +490,77 @@ int TestIterator()
intVector[0] = 20;
EATEST_VERIFY(*itVector == 20);
static_assert((eastl::is_same<decltype(eastl::unwrap_iterator(miIntVector)), eastl::vector<int>::iterator>::value == true), "unwrap_iterator failure");
+
+ eastl::reverse_iterator<eastl::vector<int>::iterator> riIntVector = intVector.rbegin();
+ eastl::reverse_iterator<eastl::vector<int>::iterator> riUnwrapped = eastl::unwrap_iterator(riIntVector);
+ EATEST_VERIFY(*riUnwrapped == 19);
+ static_assert((eastl::is_same<decltype(eastl::unwrap_iterator(riIntVector)), eastl::reverse_iterator<eastl::vector<int>::iterator>>::value == true), "unwrap_iterator failure");
+
+ eastl::reverse_iterator<eastl::move_iterator<eastl::vector<int>::iterator>> rimiIntVec(miIntVector);
+ static_assert((eastl::is_same<decltype(eastl::unwrap_iterator(rimiIntVec)), eastl::reverse_iterator<eastl::vector<int>::iterator>>::value == true), "unwrap_iterator failure");
+
+ eastl::reverse_iterator<eastl::generic_iterator<int*>> rigiIntArray(giIntArray);
+ static_assert((eastl::is_same<decltype(eastl::unwrap_iterator(rigiIntArray)), eastl::reverse_iterator<int*>>::value == true), "unwrap_iterator failure");
+
+ eastl::deque<int> intDeque(3);
+ eastl::deque<int>::iterator begin = intDeque.begin();
+ eastl::generic_iterator<eastl::deque<int>::iterator> giWrappedBegin(begin);
+ static_assert((eastl::is_same<decltype(eastl::unwrap_iterator(giWrappedBegin)), eastl::deque<int>::iterator>::value == true), "unwrap_iterator failure");
+
+ eastl::deque<int>::iterator unwrappedBegin = eastl::unwrap_iterator(giWrappedBegin);
+ EATEST_VERIFY(begin == unwrappedBegin);
+ }
+
+ {
+ // unwrap_generic_iterator
+ int intArray[2] = {0, 1};
+ eastl::generic_iterator<int*> giIntArray(intArray);
+ int* pInt = eastl::unwrap_generic_iterator(giIntArray);
+ EATEST_VERIFY(*pInt == 0);
+ static_assert((eastl::is_same<decltype(eastl::unwrap_generic_iterator(giIntArray)), int*>::value == true), "unwrap_iterator failure");
+
+ eastl::move_iterator<int*> miIntArray(intArray);
+ static_assert((eastl::is_same<decltype(eastl::unwrap_generic_iterator(miIntArray)), eastl::move_iterator<int*>>::value == true), "unwrap_iterator failure");
+
+ eastl::vector<int> intVector(1, 1);
+ eastl::generic_iterator<eastl::vector<int>::iterator> giVectorInt(intVector.begin());
+ eastl::vector<int>::iterator it = unwrap_generic_iterator(giVectorInt);
+ EATEST_VERIFY(*it == 1);
+ static_assert((eastl::is_same<decltype(eastl::unwrap_generic_iterator(giVectorInt)), eastl::vector<int>::iterator>::value == true), "unwrap_iterator failure");
+ }
+
+ {
+ // unwrap_move_iterator
+ int intArray[2] = {0, 1};
+ eastl::move_iterator<int*> miIntArray(intArray);
+ int* pInt = eastl::unwrap_move_iterator(miIntArray);
+ EATEST_VERIFY(*pInt == 0);
+ static_assert((eastl::is_same<decltype(eastl::unwrap_move_iterator(miIntArray)), int*>::value == true), "unwrap_iterator failure");
+
+ eastl::generic_iterator<int*> giIntArray(intArray);
+ static_assert((eastl::is_same<decltype(eastl::unwrap_move_iterator(giIntArray)), eastl::generic_iterator<int*>>::value == true), "unwrap_iterator failure");
+
+ eastl::vector<int> intVector(1, 1);
+ eastl::move_iterator<eastl::vector<int>::iterator> miVectorInt(intVector.begin());
+ eastl::vector<int>::iterator it = unwrap_move_iterator(miVectorInt);
+ EATEST_VERIFY(*it == 1);
+ static_assert((eastl::is_same<decltype(eastl::unwrap_move_iterator(miVectorInt)), eastl::vector<int>::iterator>::value == true), "unwrap_iterator failure");
+ }
+
+ {
+ // array cbegin - cend
+ int arr[3]{ 1, 2, 3 };
+ auto b = eastl::cbegin(arr);
+ auto e = eastl::cend(arr);
+ EATEST_VERIFY(*b == 1);
+
+ auto dist = eastl::distance(b,e);
+ EATEST_VERIFY(dist == 3);
+ }
+
+ {
+ // Regression test that ensure N3844 is working correctly.
+ static_assert(!eastl::is_detected<detect_iterator_traits_reference, int>::value, "detecting iterator_traits<int> should SFINAE gracefully.");
}
return nErrorCount;