Adding missing C++20 std::erase implementations (#5735)

There were already implementations for std::erase_if.
This adds the counterpart AZStd::erase versions

resolves #5734

Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
monroegm-disable-blank-issue-2
lumberyard-employee-dm 4 years ago committed by GitHub
parent 14ad3b025a
commit 97106f9e60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1233,6 +1233,14 @@ namespace AZStd
right.swap(AZStd::forward<this_type>(left));
}
template<class T, class Allocator, AZStd::size_t NumElementsPerBlock, AZStd::size_t MinMapSize, class U>
decltype(auto) erase(deque<T, Allocator, NumElementsPerBlock, MinMapSize>& container, const U& value)
{
auto iter = AZStd::remove(container.begin(), container.end(), value);
auto removedCount = AZStd::distance(iter, container.end());
container.erase(iter, container.end());
return removedCount;
}
template<class T, class Allocator, AZStd::size_t NumElementsPerBlock, AZStd::size_t MinMapSize, class Predicate>
decltype(auto) erase_if(deque<T, Allocator, NumElementsPerBlock, MinMapSize>& container, Predicate predicate)
{

@ -974,4 +974,22 @@ namespace AZStd
{
return !operator<(a, b);
}
// C++20 erase free functions
template<class T, size_t Capacity, class U>
constexpr decltype(auto) erase(fixed_vector<T, Capacity>& container, const U& value)
{
auto iter = AZStd::remove(container.begin(), container.end(), value);
auto removedCount = AZStd::distance(iter, container.end());
container.erase(iter, container.end());
return removedCount;
}
template<class T, size_t Capacity, class Predicate>
constexpr decltype(auto) erase_if(fixed_vector<T, Capacity>& container, Predicate predicate)
{
auto iter = AZStd::remove_if(container.begin(), container.end(), predicate);
auto removedCount = AZStd::distance(iter, container.end());
container.erase(iter, container.end());
return removedCount;
}
}

@ -1275,6 +1275,11 @@ namespace AZStd
return !(left == right);
}
template<class T, class Allocator, class U>
decltype(auto) erase(forward_list<T, Allocator>& container, const U& value)
{
return container.remove(value);
}
template<class T, class Allocator, class Predicate>
decltype(auto) erase_if(forward_list<T, Allocator>& container, Predicate predicate)
{

@ -1340,6 +1340,11 @@ namespace AZStd
return !(left == right);
}
template<class T, class Allocator, class U>
decltype(auto) erase(list<T, Allocator>& container, const U& value)
{
return container.remove(value);
}
template<class T, class Allocator, class Predicate>
decltype(auto) erase_if(list<T, Allocator>& container, Predicate predicate)
{

@ -1387,6 +1387,14 @@ namespace AZStd
}
//#pragma endregion
template<class T, class Allocator, class U>
decltype(auto) erase(vector<T, Allocator>& container, const U& value)
{
auto iter = AZStd::remove(container.begin(), container.end(), value);
auto removedCount = AZStd::distance(iter, container.end());
container.erase(iter, container.end());
return removedCount;
}
template<class T, class Allocator, class Predicate>
decltype(auto) erase_if(vector<T, Allocator>& container, Predicate predicate)
{

@ -465,6 +465,15 @@ namespace AZStd
template<class Element, size_t MaxElementCount, class Traits>
constexpr bool operator>=(const Element* lhs, const basic_fixed_string<Element, MaxElementCount, Traits>& rhs);
// C++20 erase helpers
template<class Element, size_t MaxElementCount, class Traits, class U>
constexpr auto erase(basic_fixed_string<Element, MaxElementCount, Traits>& container, const U& element)
-> typename basic_fixed_string<Element, MaxElementCount, Traits>::size_type;
template<class Element, size_t MaxElementCount, class Traits, class Predicate>
constexpr auto erase_if(basic_fixed_string<Element, MaxElementCount, Traits>& container, Predicate predicate)
-> typename basic_fixed_string<Element, MaxElementCount, Traits>::size_type;
template<class T>
struct hash;

@ -11,7 +11,7 @@
#include <stdarg.h>
#include <cstring>
#include <AzCore/std/typetraits/is_integral.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/string/fixed_string_Platform.inl>
@ -1680,6 +1680,26 @@ namespace AZStd
return !operator<(lhs, rhs);
}
template<class Element, size_t MaxElementCount, class Traits, class U>
inline constexpr auto erase(basic_fixed_string<Element, MaxElementCount, Traits>& container, const U& element)
-> typename basic_fixed_string<Element, MaxElementCount, Traits>::size_type
{
auto iter = AZStd::remove(container.begin(), container.end(), element);
auto removedCount = AZStd::distance(iter, container.end());
container.erase(iter, container.end());
return removedCount;
}
template<class Element, size_t MaxElementCount, class Traits, class Predicate>
inline constexpr auto erase_if(basic_fixed_string<Element, MaxElementCount, Traits>& container, Predicate predicate)
-> typename basic_fixed_string<Element, MaxElementCount, Traits>::size_type
{
auto iter = AZStd::remove_if(container.begin(), container.end(), predicate);
auto removedCount = AZStd::distance(iter, container.end());
container.erase(iter, container.end());
return removedCount;
}
template<class Element, size_t MaxElementCount, class Traits>
struct hash<basic_fixed_string<Element, MaxElementCount, Traits>>
{

@ -1955,6 +1955,16 @@ namespace AZStd
{
return basic_string<Element, Traits, Allocator>(lhs).compare(rhs) >= 0;
}
template<class Element, class Traits, class Allocator, class U>
decltype(auto) erase(basic_string<Element, Traits, Allocator>& container, const U& element)
{
auto iter = AZStd::remove(container.begin(), container.end(), element);
auto removedCount = AZStd::distance(iter, container.end());
container.erase(iter, container.end());
return removedCount;
}
template<class Element, class Traits, class Allocator, class Predicate>
decltype(auto) erase_if(basic_string<Element, Traits, Allocator>& container, Predicate predicate)
{

@ -2376,17 +2376,52 @@ namespace UnitTest
static_assert(AZStd::wildcard_match_case(filter1, blahValue));
}
TEST_F(String, StringEraseIf_Succeeds)
TEST_F(String, StringCXX20Erase_Succeeds)
{
AZStd::string eraseIfTest = "ABC CBA";
auto eraseCount = AZStd::erase_if(eraseIfTest, [](AZStd::string::value_type ch)
{
return ch == 'C';
});
auto erasePredicate = [](AZStd::string::value_type ch)
{
return ch == 'C';
};
auto eraseCount = AZStd::erase_if(eraseIfTest, erasePredicate);
EXPECT_EQ(2, eraseCount);
EXPECT_EQ(5, eraseIfTest.size());
EXPECT_STREQ("AB BA", eraseIfTest.c_str());
// Now erase the letter 'A';
eraseCount = AZStd::erase(eraseIfTest, 'A');
EXPECT_EQ(2, eraseCount);
EXPECT_EQ(3, eraseIfTest.size());
EXPECT_EQ("B B", eraseIfTest);
}
TEST_F(String, FixedStringCXX20Erase_Succeeds)
{
// Erase 'l' from the phrase "Hello" World"
constexpr auto eraseTest = [](const char* testString) constexpr
{
AZStd::fixed_string<16> testResult{ testString };
AZStd::erase(testResult, 'l');
return testResult;
}("HelloWorld");
static_assert(eraseTest == "HeoWord");
EXPECT_EQ("HeoWord", eraseTest);
// Use erase_if to erase both 'H' and 'e' from the remaining eraseTest string
constexpr auto eraseIfTest = [](AZStd::string_view testString) constexpr
{
AZStd::fixed_string<16> testResult{ testString };
auto erasePredicate = [](char ch)
{
return ch == 'H' || ch == 'e';
};
AZStd::erase_if(testResult, erasePredicate);
return testResult;
}(eraseTest);
static_assert(eraseIfTest == "oWord");
EXPECT_EQ("oWord", eraseIfTest);
}
template <typename StringType>

@ -796,6 +796,37 @@ namespace UnitTest
EXPECT_GT(greaterVectorDifferentSize, lessVector);
}
TEST_F(Arrays, FixedVectorCXX20Erase_Succeeds)
{
// Erase 'l' from the phrase "Hello" World"
auto eraseTest = [](AZStd::initializer_list<char> testInit) constexpr
{
AZStd::fixed_vector<char, 16> testResult{ testInit };
AZStd::erase(testResult, 'l');
return testResult;
}({ 'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd' });
constexpr AZStd::string_view expectedEraseString = "HeoWord";
AZStd::string_view testEraseString{ eraseTest.begin(), eraseTest.end() };
EXPECT_EQ(expectedEraseString, testEraseString);
// Use erase_if to erase both 'H' and 'e' from the remaining eraseTest string
auto eraseIfTest = [](const AZStd::fixed_vector<char, 16>& testVector) constexpr
{
AZStd::fixed_vector<char, 16> testResult{ testVector };
auto erasePredicate = [](char ch)
{
return ch == 'H' || ch == 'e';
};
AZStd::erase_if(testResult, erasePredicate);
return testResult;
}(testEraseString);
constexpr AZStd::string_view expectedEraseIfString = "oWord";
AZStd::string_view testEraseIfString{ eraseIfTest.begin(), eraseIfTest.end() };
EXPECT_EQ(expectedEraseIfString, testEraseIfString);
}
TEST_F(Arrays, VectorSwap)
{
vector<void*> vec1(42, nullptr);

Loading…
Cancel
Save