diff --git a/doc/EASTL.natvis b/doc/EASTL.natvis index e6bbad0d..e04f2d57 100644 --- a/doc/EASTL.natvis +++ b/doc/EASTL.natvis @@ -151,24 +151,24 @@ - + [0] {{}} - - [1] {{ {((eastl::ListNode<$T1>*)mNode.mpNext)->mValue} }} + + [1] {{ {((eastl::ListNode<$T1>*)mNodeAllocator.mFirst.mpNext)->mValue} }} - + [2] {{ - {((eastl::ListNode<$T1>*)mNode.mpNext)->mValue}, - {((eastl::ListNode<$T1>*)mNode.mpNext->mpNext)->mValue} + {((eastl::ListNode<$T1>*)mNodeAllocator.mFirst.mpNext)->mValue}, + {((eastl::ListNode<$T1>*)mNodeAllocator.mFirst.mpNext->mpNext)->mValue} }} - + [?] {{ - {((eastl::ListNode<$T1>*)mNode.mpNext)->mValue}, - {((eastl::ListNode<$T1>*)mNode.mpNext->mpNext)->mValue}, + {((eastl::ListNode<$T1>*)mNodeAllocator.mFirst.mpNext)->mValue}, + {((eastl::ListNode<$T1>*)mNodeAllocator.mFirst.mpNext->mpNext)->mValue}, ... }} @@ -177,7 +177,7 @@ Content of lists will repeat indefinitely. Keep that in mind! - mNode.mpNext + mNodeAllocator.mFirst.mpNext mpNext ((eastl::ListNode<$T1>*)this)->mValue diff --git a/include/EASTL/deque.h b/include/EASTL/deque.h index a48db537..313594b6 100644 --- a/include/EASTL/deque.h +++ b/include/EASTL/deque.h @@ -2651,6 +2651,25 @@ namespace eastl a.swap(b); } + /////////////////////////////////////////////////////////////////////// + // erase / erase_if + // + // https://en.cppreference.com/w/cpp/container/deque/erase2 + /////////////////////////////////////////////////////////////////////// + template + void erase(deque& c, const U& value) + { + // Erases all elements that compare equal to value from the container. + c.erase(eastl::remove(c.begin(), c.end(), value), c.end()); + } + + template + void erase_if(deque& c, Predicate predicate) + { + // Erases all elements that satisfy the predicate pred from the container. + c.erase(eastl::remove_if(c.begin(), c.end(), predicate), c.end()); + } + } // namespace eastl diff --git a/include/EASTL/hash_map.h b/include/EASTL/hash_map.h index 984f9985..c363597f 100644 --- a/include/EASTL/hash_map.h +++ b/include/EASTL/hash_map.h @@ -288,9 +288,25 @@ namespace eastl }; // hash_map - - - + /// hash_map erase_if + /// + /// https://en.cppreference.com/w/cpp/container/unordered_map/erase_if + template + void erase_if(eastl::hash_map& c, UserPredicate predicate) + { + // Erases all elements that satisfy the predicate from the container. + for (auto i = c.begin(), last = c.end(); i != last;) + { + if (predicate(*i)) + { + i = c.erase(i); + } + else + { + ++i; + } + } + } /// hash_multimap @@ -436,9 +452,28 @@ namespace eastl return base_type::DoInsertKey(false_type(), eastl::move(key)); } - }; // hash_multimap + /// hash_multimap erase_if + /// + /// https://en.cppreference.com/w/cpp/container/unordered_multimap/erase_if + template + void erase_if(eastl::hash_multimap& c, UserPredicate predicate) + { + // Erases all elements that satisfy the predicate from the container. + for (auto i = c.begin(), last = c.end(); i != last;) + { + if (predicate(*i)) + { + i = c.erase(i); + } + else + { + ++i; + } + } + } + /////////////////////////////////////////////////////////////////////// diff --git a/include/EASTL/hash_set.h b/include/EASTL/hash_set.h index 0dd7435e..c075975d 100644 --- a/include/EASTL/hash_set.h +++ b/include/EASTL/hash_set.h @@ -203,9 +203,25 @@ namespace eastl }; // hash_set - - - + /// hash_set erase_if + /// + /// https://en.cppreference.com/w/cpp/container/unordered_set/erase_if + template + void erase_if(eastl::hash_set& c, UserPredicate predicate) + { + // Erases all elements that satisfy the predicate pred from the container. + for (auto i = c.begin(), last = c.end(); i != last;) + { + if (predicate(*i)) + { + i = c.erase(i); + } + else + { + ++i; + } + } + } /// hash_multiset @@ -321,6 +337,26 @@ namespace eastl }; // hash_multiset + /// hash_multiset erase_if + /// + /// https://en.cppreference.com/w/cpp/container/unordered_multiset/erase_if + template + void erase_if(eastl::hash_multiset& c, UserPredicate predicate) + { + // Erases all elements that satisfy the predicate pred from the container. + for (auto i = c.begin(), last = c.end(); i != last;) + { + if (predicate(*i)) + { + i = c.erase(i); + } + else + { + ++i; + } + } + } + /////////////////////////////////////////////////////////////////////// diff --git a/include/EASTL/internal/config.h b/include/EASTL/internal/config.h index d1544309..f9c4b001 100644 --- a/include/EASTL/internal/config.h +++ b/include/EASTL/internal/config.h @@ -89,8 +89,8 @@ /////////////////////////////////////////////////////////////////////////////// #ifndef EASTL_VERSION - #define EASTL_VERSION "3.15.00" - #define EASTL_VERSION_N 31500 + #define EASTL_VERSION "3.16.01" + #define EASTL_VERSION_N 31601 #endif @@ -143,20 +143,18 @@ // http://en.wikipedia.org/wiki/C%2B%2B14#Relaxed_constexpr_restrictions // #if !defined(EA_CPP14_CONSTEXPR) + #if defined(EA_COMPILER_MSVC_2015) - #define EA_CPP14_CONSTEXPR // not supported - #define EA_NO_CPP14_CONSTEXPR - #elif defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION < 9000) // Before GCC 9.0 - #define EA_CPP14_CONSTEXPR // not supported - #define EA_NO_CPP14_CONSTEXPR - #elif defined(EA_COMPILER_CLANG) && (EA_COMPILER_VERSION < 500) // Before clang5 - #define EA_CPP14_CONSTEXPR // not supported - #define EA_NO_CPP14_CONSTEXPR + #define EA_CPP14_CONSTEXPR // not supported + #define EA_NO_CPP14_CONSTEXPR + #elif defined(__GNUC__) && (EA_COMPILER_VERSION < 9000) // Before GCC 9.0 + #define EA_CPP14_CONSTEXPR // not supported + #define EA_NO_CPP14_CONSTEXPR #elif defined(EA_COMPILER_CPP14_ENABLED) #define EA_CPP14_CONSTEXPR constexpr #else - #define EA_CPP14_CONSTEXPR // not supported - #define EA_NO_CPP14_CONSTEXPR + #define EA_CPP14_CONSTEXPR // not supported + #define EA_NO_CPP14_CONSTEXPR #endif #endif diff --git a/include/EASTL/list.h b/include/EASTL/list.h index 3403a57e..8099c242 100644 --- a/include/EASTL/list.h +++ b/include/EASTL/list.h @@ -2138,6 +2138,26 @@ namespace eastl } + /////////////////////////////////////////////////////////////////////// + // erase / erase_if + // + // https://en.cppreference.com/w/cpp/container/list/erase2 + /////////////////////////////////////////////////////////////////////// + template + void erase(list& c, const U& value) + { + // Erases all elements that compare equal to value from the container. + c.remove_if([&](auto& elem) { return elem == value; }); + } + + template + void erase_if(list& c, Predicate predicate) + { + // Erases all elements that satisfy the predicate pred from the container. + c.remove_if(predicate); + } + + } // namespace eastl diff --git a/include/EASTL/map.h b/include/EASTL/map.h index 1b1d8977..0e6c1d0f 100644 --- a/include/EASTL/map.h +++ b/include/EASTL/map.h @@ -476,7 +476,26 @@ namespace eastl } - + /////////////////////////////////////////////////////////////////////// + // erase_if + // + // https://en.cppreference.com/w/cpp/container/map/erase_if + /////////////////////////////////////////////////////////////////////// + template + void erase_if(map& c, Predicate predicate) + { + for (auto i = c.begin(), last = c.end(); i != last;) + { + if (predicate(*i)) + { + i = c.erase(i); + } + else + { + ++i; + } + } + } /////////////////////////////////////////////////////////////////////// @@ -633,6 +652,27 @@ namespace eastl + /////////////////////////////////////////////////////////////////////// + // erase_if + // + // https://en.cppreference.com/w/cpp/container/multimap/erase_if + /////////////////////////////////////////////////////////////////////// + template + void erase_if(multimap& c, Predicate predicate) + { + // Erases all elements that satisfy the predicate pred from the container. + for (auto i = c.begin(), last = c.end(); i != last;) + { + if (predicate(*i)) + { + i = c.erase(i); + } + else + { + ++i; + } + } + } } // namespace eastl diff --git a/include/EASTL/set.h b/include/EASTL/set.h index 4f52373e..a66a8853 100644 --- a/include/EASTL/set.h +++ b/include/EASTL/set.h @@ -395,7 +395,26 @@ namespace eastl } - + /////////////////////////////////////////////////////////////////////// + // erase_if + // + // https://en.cppreference.com/w/cpp/container/set/erase_if + /////////////////////////////////////////////////////////////////////// + template + void erase_if(set& c, Predicate predicate) + { + for (auto i = c.begin(), last = c.end(); i != last;) + { + if (predicate(*i)) + { + i = c.erase(i); + } + else + { + ++i; + } + } + } /////////////////////////////////////////////////////////////////////// @@ -586,6 +605,28 @@ namespace eastl } + /////////////////////////////////////////////////////////////////////// + // erase_if + // + // https://en.cppreference.com/w/cpp/container/multiset/erase_if + /////////////////////////////////////////////////////////////////////// + template + void erase_if(multiset& c, Predicate predicate) + { + // Erases all elements that satisfy the predicate pred from the container. + for (auto i = c.begin(), last = c.end(); i != last;) + { + if (predicate(*i)) + { + i = c.erase(i); + } + else + { + ++i; + } + } + } + } // namespace eastl diff --git a/include/EASTL/slist.h b/include/EASTL/slist.h index 3ee4cfbc..a3a0823a 100644 --- a/include/EASTL/slist.h +++ b/include/EASTL/slist.h @@ -1856,6 +1856,24 @@ namespace eastl } + /// erase / erase_if + /// + /// https://en.cppreference.com/w/cpp/container/forward_list/erase2 + template + void erase(slist& c, const U& value) + { + // Erases all elements that compare equal to value from the container. + c.remove_if([&](auto& elem) { return elem == value; }); + } + + template + void erase_if(slist& c, Predicate predicate) + { + // Erases all elements that satisfy the predicate pred from the container. + c.remove_if(predicate); + } + + /// insert_iterator /// /// We borrow a trick from SGI STL here and define an insert_iterator diff --git a/include/EASTL/span.h b/include/EASTL/span.h index f433d14b..0cdb1026 100644 --- a/include/EASTL/span.h +++ b/include/EASTL/span.h @@ -84,13 +84,13 @@ namespace eastl enable_if_t && !is_same_v> && !is_array_v && Internal::HasSizeAndData::value && - is_convertible_v()))> (*)[], element_type (*)[]>>; + is_convertible_v()))> (*)[], element_type (*)[]>>; // generic container conversion constructors template > EA_CONSTEXPR span(Container& cont); - template > + template > EA_CONSTEXPR span(const Container& cont); template )>> @@ -141,12 +141,13 @@ namespace eastl /////////////////////////////////////////////////////////////////////////// // template deduction guides /////////////////////////////////////////////////////////////////////////// - - // template span(T (&)[N]) -> span ; - // template span(array&) -> span ; - // template span(const array&) -> span ; - // template span(Container&) -> span ; - // template span(const Container&) -> span ; + #ifdef __cpp_deduction_guides + template span(T (&)[N]) -> span ; + template span(array&) -> span ; + template span(const array&) -> span ; + template span(Container&) -> span ; + template span(const Container&) -> span ; + #endif /////////////////////////////////////////////////////////////////////////// diff --git a/include/EASTL/string.h b/include/EASTL/string.h index 74e248b5..14f113dd 100644 --- a/include/EASTL/string.h +++ b/include/EASTL/string.h @@ -4056,6 +4056,23 @@ namespace eastl EA_RESTORE_VC_WARNING() // warning: 4455 #endif + + /// erase / erase_if + /// + /// https://en.cppreference.com/w/cpp/string/basic_string/erase2 + template + void erase(basic_string& c, const U& value) + { + // Erases all elements that compare equal to value from the container. + c.erase(eastl::remove(c.begin(), c.end(), value), c.end()); + } + + template + void erase_if(basic_string& c, Predicate predicate) + { + // Erases all elements that satisfy the predicate pred from the container. + c.erase(eastl::remove_if(c.begin(), c.end(), predicate), c.end()); + } } // namespace eastl diff --git a/include/EASTL/tuple.h b/include/EASTL/tuple.h index 325570cf..f9611e21 100644 --- a/include/EASTL/tuple.h +++ b/include/EASTL/tuple.h @@ -985,7 +985,7 @@ EA_CONSTEXPR decltype(auto) apply(F&& f, Tuple&& t) EA_DISABLE_CLANG_WARNING(-Wmismatched-tags) template - class tuple_size<::eastl::tuple> : ::eastl::integral_constant + class tuple_size<::eastl::tuple> : public ::eastl::integral_constant { }; diff --git a/include/EASTL/unordered_map.h b/include/EASTL/unordered_map.h index d113da9d..10c6b882 100644 --- a/include/EASTL/unordered_map.h +++ b/include/EASTL/unordered_map.h @@ -33,6 +33,7 @@ namespace eastl using unordered_map = hash_map; #endif + /// unordered_multimap /// /// Similar template alias as "unordered_map" except the contained elements diff --git a/include/EASTL/variant.h b/include/EASTL/variant.h index ed8ca118..8e6a549f 100644 --- a/include/EASTL/variant.h +++ b/include/EASTL/variant.h @@ -261,15 +261,18 @@ namespace eastl }; // handler function - using StorageHandlerPtr = void(*)(StorageOp, void*, void*); + using storage_handler_ptr = void(*)(StorageOp, void*, void*); using aligned_storage_impl_t = aligned_union_t<16, Types...>; aligned_storage_impl_t mBuffer; - StorageHandlerPtr mpHandler = nullptr; + storage_handler_ptr mpHandler = nullptr; template inline void DoOp(StorageOp op, VariantStorageT&& other) // bind to both rvalue and lvalues { + if(mpHandler) + DoOp(StorageOp::DESTROY); + if (other.mpHandler) mpHandler = other.mpHandler; @@ -361,7 +364,7 @@ namespace eastl new (&mBuffer) RT(eastl::forward(args)...); - mpHandler = (StorageHandlerPtr)&DoOpImpl; + mpHandler = (storage_handler_ptr)&DoOpImpl; } template @@ -376,7 +379,7 @@ namespace eastl new (&mBuffer) RT(il, eastl::forward(args)...); - mpHandler = (StorageHandlerPtr)&DoOpImpl; + mpHandler = (storage_handler_ptr)&DoOpImpl; } template diff --git a/include/EASTL/vector.h b/include/EASTL/vector.h index f7ec1939..e1049cbb 100644 --- a/include/EASTL/vector.h +++ b/include/EASTL/vector.h @@ -293,13 +293,9 @@ namespace eastl template iterator insert(const_iterator position, InputIterator first, InputIterator last); - template >> iterator erase_first(const T& value); - template >> iterator erase_first_unsorted(const T& value); // Same as erase, except it doesn't preserve order, but is faster because it simply copies the last item in the vector over the erased position. - template >> reverse_iterator erase_last(const T& value); - template >> reverse_iterator erase_last_unsorted(const T& value); // Same as erase, except it doesn't preserve order, but is faster because it simply copies the last item in the vector over the erased position. iterator erase(const_iterator position); @@ -1237,9 +1233,10 @@ namespace eastl } template - template inline typename vector::iterator vector::erase_first(const T& value) { + static_assert(eastl::has_equality_v, "T must be comparable"); + iterator it = eastl::find(begin(), end(), value); if (it != end()) @@ -1249,10 +1246,11 @@ namespace eastl } template - template inline typename vector::iterator vector::erase_first_unsorted(const T& value) { + static_assert(eastl::has_equality_v, "T must be comparable"); + iterator it = eastl::find(begin(), end(), value); if (it != end()) @@ -1262,10 +1260,11 @@ namespace eastl } template - template inline typename vector::reverse_iterator vector::erase_last(const T& value) { + static_assert(eastl::has_equality_v, "T must be comparable"); + reverse_iterator it = eastl::find(rbegin(), rend(), value); if (it != rend()) @@ -1275,10 +1274,11 @@ namespace eastl } template - template inline typename vector::reverse_iterator vector::erase_last_unsorted(const T& value) { + static_assert(eastl::has_equality_v, "T must be comparable"); + reverse_iterator it = eastl::find(rbegin(), rend(), value); if (it != rend()) @@ -2021,6 +2021,26 @@ namespace eastl } + + /////////////////////////////////////////////////////////////////////// + // erase / erase_if + // + // https://en.cppreference.com/w/cpp/container/vector/erase2 + /////////////////////////////////////////////////////////////////////// + template + void erase(vector& c, const U& value) + { + // Erases all elements that compare equal to value from the container. + c.erase(eastl::remove(c.begin(), c.end(), value), c.end()); + } + + template + void erase_if(vector& c, Predicate predicate) + { + // Erases all elements that satisfy the predicate pred from the container. + c.erase(eastl::remove_if(c.begin(), c.end(), predicate), c.end()); + } + } // namespace eastl diff --git a/test/packages/EABase b/test/packages/EABase index d62990dc..edbafca8 160000 --- a/test/packages/EABase +++ b/test/packages/EABase @@ -1 +1 @@ -Subproject commit d62990dc0a11e0cbc483580d7617ce95ec7a123a +Subproject commit edbafca82e4c4e73302e0b5144c5d1f4710db9fa diff --git a/test/packages/EAStdC b/test/packages/EAStdC index 93e6c4f7..4828af4c 160000 --- a/test/packages/EAStdC +++ b/test/packages/EAStdC @@ -1 +1 @@ -Subproject commit 93e6c4f79eb36727a95803e173b11c27d199642f +Subproject commit 4828af4c23f50aeed96a74b8f4dfc3bfb6e594ae diff --git a/test/source/EASTLTest.h b/test/source/EASTLTest.h index be42d587..6182fc7f 100644 --- a/test/source/EASTLTest.h +++ b/test/source/EASTLTest.h @@ -68,7 +68,6 @@ int TestSet(); int TestSmartPtr(); int TestSort(); int TestSpan(); -int TestSparseMatrix(); int TestString(); int TestStringHashMap(); int TestStringMap(); diff --git a/test/source/EASTLTestAllocator.cpp b/test/source/EASTLTestAllocator.cpp index ab358853..0f03d8ac 100644 --- a/test/source/EASTLTestAllocator.cpp +++ b/test/source/EASTLTestAllocator.cpp @@ -302,7 +302,7 @@ } - _Ret_notnull_ _Post_writable_byte_size_(size) void* operator new(size_t size) EA_THROW_SPEC_NEW(std::bad_alloc) + _Ret_notnull_ _Post_writable_byte_size_(size) void* operator new(size_t size) { gEASTLTest_AllocationCount++; gEASTLTest_TotalAllocationCount++; @@ -320,7 +320,7 @@ } - _Ret_notnull_ _Post_writable_byte_size_(size) void* operator new[](size_t size) EA_THROW_SPEC_NEW(std::bad_alloc) + _Ret_notnull_ _Post_writable_byte_size_(size) void* operator new[](size_t size) { gEASTLTest_AllocationCount++; gEASTLTest_TotalAllocationCount++; diff --git a/test/source/TestDeque.cpp b/test/source/TestDeque.cpp index 6c86731f..99076ff4 100644 --- a/test/source/TestDeque.cpp +++ b/test/source/TestDeque.cpp @@ -1058,6 +1058,34 @@ int TestDeque() #endif } + + { // Test erase / erase_if + { + eastl::deque d = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + + eastl::erase(d, 2); + VERIFY((d == eastl::deque{1, 3, 4, 5, 6, 7, 8, 9})); + + eastl::erase(d, 7); + VERIFY((d == eastl::deque{1, 3, 4, 5, 6, 8, 9})); + + eastl::erase(d, 9); + VERIFY((d == eastl::deque{1, 3, 4, 5, 6, 8})); + + eastl::erase(d, 5); + VERIFY((d == eastl::deque{1, 3, 4, 6, 8})); + + eastl::erase(d, 3); + VERIFY((d == eastl::deque{1, 4, 6, 8})); + } + + { + eastl::deque d = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + eastl::erase_if(d, [](auto i) { return i % 2 == 0; }); + VERIFY((d == eastl::deque{1, 3, 5, 7, 9})); + } + } + return nErrorCount; } diff --git a/test/source/TestHash.cpp b/test/source/TestHash.cpp index 832dad31..737d3a63 100644 --- a/test/source/TestHash.cpp +++ b/test/source/TestHash.cpp @@ -704,25 +704,23 @@ int TestHash() // const Predicate& predicate = Predicate(), const allocator_type& allocator = EASTL_HASH_SET_DEFAULT_ALLOCATOR) // this_type& operator=(std::initializer_list ilist); // void insert(std::initializer_list ilist); - #if !defined(EA_COMPILER_NO_INITIALIZER_LISTS) - hash_set intHashSet = { 12, 13, 14 }; - EATEST_VERIFY(intHashSet.size() == 3); - EATEST_VERIFY(intHashSet.find(12) != intHashSet.end()); - EATEST_VERIFY(intHashSet.find(13) != intHashSet.end()); - EATEST_VERIFY(intHashSet.find(14) != intHashSet.end()); - - intHashSet = { 22, 23, 24 }; - EATEST_VERIFY(intHashSet.size() == 3); - EATEST_VERIFY(intHashSet.find(22) != intHashSet.end()); - EATEST_VERIFY(intHashSet.find(23) != intHashSet.end()); - EATEST_VERIFY(intHashSet.find(24) != intHashSet.end()); - - intHashSet.insert({ 42, 43, 44 }); - EATEST_VERIFY(intHashSet.size() == 6); - EATEST_VERIFY(intHashSet.find(42) != intHashSet.end()); - EATEST_VERIFY(intHashSet.find(43) != intHashSet.end()); - EATEST_VERIFY(intHashSet.find(44) != intHashSet.end()); - #endif + hash_set intHashSet = { 12, 13, 14 }; + EATEST_VERIFY(intHashSet.size() == 3); + EATEST_VERIFY(intHashSet.find(12) != intHashSet.end()); + EATEST_VERIFY(intHashSet.find(13) != intHashSet.end()); + EATEST_VERIFY(intHashSet.find(14) != intHashSet.end()); + + intHashSet = { 22, 23, 24 }; + EATEST_VERIFY(intHashSet.size() == 3); + EATEST_VERIFY(intHashSet.find(22) != intHashSet.end()); + EATEST_VERIFY(intHashSet.find(23) != intHashSet.end()); + EATEST_VERIFY(intHashSet.find(24) != intHashSet.end()); + + intHashSet.insert({ 42, 43, 44 }); + EATEST_VERIFY(intHashSet.size() == 6); + EATEST_VERIFY(intHashSet.find(42) != intHashSet.end()); + EATEST_VERIFY(intHashSet.find(43) != intHashSet.end()); + EATEST_VERIFY(intHashSet.find(44) != intHashSet.end()); } { @@ -734,6 +732,21 @@ int TestHash() } + { // hash_set erase_if + hash_set m = {0, 1, 2, 3, 4}; + eastl::erase_if(m, [](auto i) { return i % 2 == 0; }); + VERIFY((m == hash_set{1, 3})); + } + + { // hash_multiset erase_if + hash_multiset m = {0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 4}; + eastl::erase_if(m, [](auto i) { return i % 2 == 0; }); + VERIFY((m == hash_multiset{1, 1, 1, 3})); + } + + + + { // Test hash_map @@ -916,6 +929,20 @@ int TestHash() } } + { // hash_map erase_if + hash_map m = {{0, 0}, {1, 1}, {2, 2}, {3, 3}, {4, 4}}; + eastl::erase_if(m, [](auto p) { return p.first % 2 == 0; }); + VERIFY((m == hash_map{{1, 1}, {3, 3}})); + } + + { // hash_multimap erase_if + hash_multimap m = {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 1}, {2, 2}, + {2, 2}, {2, 2}, {2, 2}, {3, 3}, {3, 3}, {4, 4}}; + eastl::erase_if(m, [](auto p) { return p.first % 2 == 0; }); + VERIFY((m == hash_multimap{{1, 1}, {3, 3}, {3, 3}})); + } + + { // template diff --git a/test/source/TestList.cpp b/test/source/TestList.cpp index ed86baf7..8a5e0573 100644 --- a/test/source/TestList.cpp +++ b/test/source/TestList.cpp @@ -971,6 +971,24 @@ int TestList() EATEST_VERIFY(sizeof(list1) < sizeof(list2)); } + { // Test erase / erase_if + { + eastl::list l = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + + eastl::erase(l, 3); + eastl::erase(l, 5); + eastl::erase(l, 7); + + VERIFY((l == eastl::list{1, 2, 4, 6, 8, 9})); + } + + { + eastl::list l = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + eastl::erase_if(l, [](auto i) { return i % 2 == 0; }); + VERIFY((l == eastl::list{1, 3, 5, 7, 9})); + } + } + return nErrorCount; } diff --git a/test/source/TestMap.cpp b/test/source/TestMap.cpp index d2a9a7c7..cce6cc1d 100644 --- a/test/source/TestMap.cpp +++ b/test/source/TestMap.cpp @@ -208,6 +208,18 @@ int TestMap() EATEST_VERIFY(sizeof(VM1) < sizeof(VM2)); } + { // Test erase_if + eastl::map m = {{0, 0}, {1, 1}, {2, 2}, {3, 3}, {4, 4}}; + eastl::erase_if(m, [](auto p) { return p.first % 2 == 0; }); + VERIFY((m == eastl::map{{1, 1},{3, 3}})); + } + + { // Test erase_if + eastl::multimap m = {{0, 0}, {0, 0}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {3, 3}, {4, 4}, {4, 4}, {4, 4}}; + eastl::erase_if(m, [](auto p) { return p.first % 2 == 0; }); + VERIFY((m == eastl::multimap{{1, 1}, {1, 1}, {3, 3}})); + } + return nErrorCount; } diff --git a/test/source/TestSList.cpp b/test/source/TestSList.cpp index 4d0a5a04..d73f2bc2 100644 --- a/test/source/TestSList.cpp +++ b/test/source/TestSList.cpp @@ -791,6 +791,40 @@ int TestSList() EATEST_VERIFY(sizeof(list1) < sizeof(list2)); } + { // Test erase / erase_if + { + slist l = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + eastl::erase(l, 5); + VERIFY((l == slist{0, 1, 2, 3, 4, 6, 7, 8, 9})); + + eastl::erase(l, 7); + VERIFY((l == slist{0, 1, 2, 3, 4, 6, 8, 9})); + + eastl::erase(l, 2); + VERIFY((l == slist{0, 1, 3, 4, 6, 8, 9})); + + eastl::erase(l, 0); + VERIFY((l == slist{1, 3, 4, 6, 8, 9})); + + eastl::erase(l, 4); + VERIFY((l == slist{1, 3, 6, 8, 9})); + } + + { + slist l = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + eastl::erase_if(l, [](auto e) { return e % 2 == 0; }); + VERIFY((l == slist{1, 3, 5, 7, 9})); + + eastl::erase_if(l, [](auto e) { return e == 5; }); + VERIFY((l == slist{1, 3, 7, 9})); + + eastl::erase_if(l, [](auto e) { return e % 3 == 0; }); + VERIFY((l == slist{1, 7})); + } + } + return nErrorCount; } diff --git a/test/source/TestSet.cpp b/test/source/TestSet.cpp index d865ab81..14159056 100644 --- a/test/source/TestSet.cpp +++ b/test/source/TestSet.cpp @@ -116,6 +116,18 @@ int TestSet() } } + { // set erase_if tests + set s = {0, 1, 2, 3, 4}; + eastl::erase_if(s, [](auto i) { return i % 2 == 0;}); + VERIFY((s == set{1,3})); + } + + { // multiset erase_if tests + multiset s = {0, 0, 0, 0, 0, 1, 1, 1, 2, 3, 3, 3, 4}; + eastl::erase_if(s, [](auto i) { return i % 2 == 0;}); + VERIFY((s == multiset{1, 1, 1, 3, 3, 3})); + } + return nErrorCount; } diff --git a/test/source/TestSpan.cpp b/test/source/TestSpan.cpp index 5cc2fc18..f5681964 100644 --- a/test/source/TestSpan.cpp +++ b/test/source/TestSpan.cpp @@ -300,6 +300,25 @@ void TestSpanContainerConversion(int& nErrorCount) VERIFY(s1.data() == v.data()); VERIFY(s1.data() == s2.data()); } + + { // user reported regression for calling non-const span overload with a vector. + auto f1 = [](span s) { return s.size(); }; + auto f2 = [](span s) { return s.size(); }; + + { + vector v = {0, 1, 2, 3, 4, 5}; + + VERIFY(f1(v) == v.size()); + VERIFY(f2(v) == v.size()); + } + + { + int a[] = {0, 1, 2, 3, 4, 5}; + + VERIFY(f1(a) == EAArrayCount(a)); + VERIFY(f2(a) == EAArrayCount(a)); + } + } } void TestSpanComparison(int& nErrorCount) diff --git a/test/source/TestString.inl b/test/source/TestString.inl index 9bfcf0c2..81b6bdb7 100644 --- a/test/source/TestString.inl +++ b/test/source/TestString.inl @@ -2020,6 +2020,24 @@ int TEST_STRING_NAME() } } + // test eastl::erase + { + StringType str(LITERAL("abcdefghijklmnopqrstuvwxyz")); + eastl::erase(str, LITERAL('a')); + eastl::erase(str, LITERAL('f')); + eastl::erase(str, LITERAL('l')); + eastl::erase(str, LITERAL('w')); + eastl::erase(str, LITERAL('y')); + VERIFY(str == LITERAL("bcdeghijkmnopqrstuvxz")); + } + + // test eastl::erase_if + { + StringType str(LITERAL("abcdefghijklmnopqrstuvwxyz")); + eastl::erase_if(str, [](auto c) { return c == LITERAL('a') || c == LITERAL('v'); }); + VERIFY(str == LITERAL("bcdefghijklmnopqrstuwxyz")); + } + return nErrorCount; } diff --git a/test/source/TestVariant.cpp b/test/source/TestVariant.cpp index f8476f37..7e62c6fc 100644 --- a/test/source/TestVariant.cpp +++ b/test/source/TestVariant.cpp @@ -780,9 +780,78 @@ void TestCompilation(const double e) { eastl::variant v{e}; } +int TestVariantUserRegressionCopyMoveAssignmentOperatorLeak() +{ + using namespace eastl; + int nErrorCount = 0; + + { + { + eastl::variant v = TestObject(1337); + VERIFY(eastl::get(v).mX == 1337); + eastl::variant v2 = TestObject(1338); + VERIFY(eastl::get(v2).mX == 1338); + v.operator=(v2); + VERIFY(eastl::get(v).mX == 1338); + VERIFY(eastl::get(v2).mX == 1338); + } + VERIFY(TestObject::IsClear()); + TestObject::Reset(); + } + { + { + eastl::variant v = TestObject(1337); + VERIFY(eastl::get(v).mX == 1337); + eastl::variant v2 = TestObject(1338); + VERIFY(eastl::get(v2).mX == 1338); + v.operator=(eastl::move(v2)); + VERIFY(eastl::get(v).mX == 1338); + } + VERIFY(TestObject::IsClear()); + TestObject::Reset(); + } + { + { + eastl::variant v = TestObject(1337); + VERIFY(eastl::get(v).mX == 1337); + v = {}; + VERIFY(eastl::get(v).mX == 0); + } + VERIFY(TestObject::IsClear()); + TestObject::Reset(); + } + + return nErrorCount; +} + + +int TestVariantUserRegressionIncompleteType() +{ + using namespace eastl; + int nErrorCount = 0; + + { + struct B; + + struct A + { + vector> v; + }; + + struct B + { + vector> v; + }; + } + + return nErrorCount; +} + + int TestVariant() { int nErrorCount = 0; + nErrorCount += TestVariantBasic(); nErrorCount += TestVariantSize(); nErrorCount += TestVariantAlternative(); @@ -798,6 +867,9 @@ int TestVariant() nErrorCount += TestVariantVisitor(); nErrorCount += TestVariantAssignment(); nErrorCount += TestVariantMoveOnly(); + nErrorCount += TestVariantUserRegressionCopyMoveAssignmentOperatorLeak(); + nErrorCount += TestVariantUserRegressionIncompleteType(); + return nErrorCount; } #else diff --git a/test/source/TestVector.cpp b/test/source/TestVector.cpp index ece462c3..0fe719d6 100644 --- a/test/source/TestVector.cpp +++ b/test/source/TestVector.cpp @@ -1713,5 +1713,27 @@ int TestVector() static_assert(sizeof(EboVector) == 3 * sizeof(void*), ""); } + // eastl::erase / eastl::erase_if tests + { + { + eastl::vector v = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + + eastl::erase(v, 5); + VERIFY((v == eastl::vector {1, 2, 3, 4, 6, 7, 8, 9})); + + eastl::erase(v, 2); + VERIFY((v == eastl::vector {1, 3, 4, 6, 7, 8, 9})); + + eastl::erase(v, 9); + VERIFY((v == eastl::vector {1, 3, 4, 6, 7, 8})); + } + + { + eastl::vector v = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + eastl::erase_if(v, [](auto i) { return i % 2 == 0; }); + VERIFY((v == eastl::vector{1, 3, 5, 7, 9})); + } + } + return nErrorCount; } diff --git a/test/source/main.cpp b/test/source/main.cpp index bb23b94e..c06d6765 100644 --- a/test/source/main.cpp +++ b/test/source/main.cpp @@ -18,7 +18,6 @@ EA_RESTORE_ALL_VC_WARNINGS() #include "EAMain/EAEntryPointMain.inl" #include "EASTLTestAllocator.h" - /////////////////////////////////////////////////////////////////////////////// // Required by EASTL. // @@ -131,7 +130,6 @@ int EAMain(int argc, char* argv[]) testSuite.AddTest("SmartPtr", TestSmartPtr); testSuite.AddTest("Sort", TestSort); testSuite.AddTest("Span", TestSpan); - testSuite.AddTest("SparseMatrix", TestSparseMatrix); testSuite.AddTest("String", TestString); testSuite.AddTest("StringHashMap", TestStringHashMap); testSuite.AddTest("StringMap", TestStringMap);