diff options
Diffstat (limited to 'EASTL/test/source/TestIterator.cpp')
-rw-r--r-- | EASTL/test/source/TestIterator.cpp | 192 |
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; |