aboutsummaryrefslogtreecommitdiff
path: root/EASTL/test
diff options
context:
space:
mode:
Diffstat (limited to 'EASTL/test')
-rw-r--r--EASTL/test/CMakeLists.txt3
-rw-r--r--EASTL/test/source/EASTLTest.h3
-rw-r--r--EASTL/test/source/TestAlgorithm.cpp235
-rw-r--r--EASTL/test/source/TestAllocator.cpp5
-rw-r--r--EASTL/test/source/TestArray.cpp47
-rw-r--r--EASTL/test/source/TestBitcast.cpp52
-rw-r--r--EASTL/test/source/TestChrono.cpp11
-rw-r--r--EASTL/test/source/TestDeque.cpp44
-rw-r--r--EASTL/test/source/TestExtra.cpp610
-rw-r--r--EASTL/test/source/TestFixedString.cpp52
-rw-r--r--EASTL/test/source/TestFunctional.cpp211
-rw-r--r--EASTL/test/source/TestHash.cpp22
-rw-r--r--EASTL/test/source/TestIntrusiveHash.cpp6
-rw-r--r--EASTL/test/source/TestIterator.cpp192
-rw-r--r--EASTL/test/source/TestList.cpp103
-rw-r--r--EASTL/test/source/TestMap.cpp78
-rw-r--r--EASTL/test/source/TestMap.h30
-rw-r--r--EASTL/test/source/TestMemory.cpp44
-rw-r--r--EASTL/test/source/TestNumericLimits.cpp5
-rw-r--r--EASTL/test/source/TestOptional.cpp58
-rw-r--r--EASTL/test/source/TestSList.cpp114
-rw-r--r--EASTL/test/source/TestSet.cpp48
-rw-r--r--EASTL/test/source/TestSmartPtr.cpp39
-rw-r--r--EASTL/test/source/TestSort.cpp42
-rw-r--r--EASTL/test/source/TestSpan.cpp20
-rw-r--r--EASTL/test/source/TestString.inl40
-rw-r--r--EASTL/test/source/TestStringView.cpp19
-rw-r--r--EASTL/test/source/TestStringView.inl80
-rw-r--r--EASTL/test/source/TestTuple.cpp51
-rw-r--r--EASTL/test/source/TestTypeTraits.cpp475
-rw-r--r--EASTL/test/source/TestUtility.cpp293
-rw-r--r--EASTL/test/source/TestVariant.cpp1025
-rw-r--r--EASTL/test/source/TestVector.cpp94
-rw-r--r--EASTL/test/source/main.cpp1
34 files changed, 3984 insertions, 168 deletions
diff --git a/EASTL/test/CMakeLists.txt b/EASTL/test/CMakeLists.txt
index 3fac51f..ff16189 100644
--- a/EASTL/test/CMakeLists.txt
+++ b/EASTL/test/CMakeLists.txt
@@ -17,6 +17,9 @@ add_definitions(-D_SCL_SECURE_NO_WARNINGS)
add_definitions(-DEASTL_OPENSOURCE=1)
add_definitions(-D_CHAR16T)
add_definitions(-DEASTL_THREAD_SUPPORT_AVAILABLE=0)
+if (EASTL_STD_ITERATOR_CATEGORY_ENABLED)
+ add_definitions(-DEASTL_STD_ITERATOR_CATEGORY_ENABLED=1)
+endif()
#-------------------------------------------------------------------------------------------
# Compiler Flags
diff --git a/EASTL/test/source/EASTLTest.h b/EASTL/test/source/EASTLTest.h
index 1cb298b..fca6b2c 100644
--- a/EASTL/test/source/EASTLTest.h
+++ b/EASTL/test/source/EASTLTest.h
@@ -82,6 +82,7 @@ int TestVectorMap();
int TestVectorSet();
int TestAtomicBasic();
int TestAtomicAsm();
+int TestBitcast();
// Now enable warnings as desired.
@@ -1260,6 +1261,8 @@ public:
activeAllocatedMemory = 0;
}
+ virtual ~CountingAllocator() = default;
+
static uint64_t activeAllocCount;
static uint64_t totalAllocCount;
static uint64_t totalDeallocCount;
diff --git a/EASTL/test/source/TestAlgorithm.cpp b/EASTL/test/source/TestAlgorithm.cpp
index 142d45e..a0f64da 100644
--- a/EASTL/test/source/TestAlgorithm.cpp
+++ b/EASTL/test/source/TestAlgorithm.cpp
@@ -1509,6 +1509,82 @@ int TestAlgorithm()
EATEST_VERIFY( b);
}
+#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+ {
+ // <compairison_category> lexicographical_compare_three_way(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare compare)
+
+ int intArray1[6] = {0, 1, 2, 3, 4, 5};
+ int intArray2[6] = {0, 1, 2, 3, 4, 6};
+ int intArray3[5] = {0, 1, 2, 3, 4};
+ int intArray4[5] = {4, 3, 2, 1, 0};
+
+ // strong ordering
+ auto compare_strong = [](int first, int second)
+ {
+ return (first < second) ? std::strong_ordering::less :
+ (first > second) ? std::strong_ordering::greater :
+ std::strong_ordering::equal;
+ };
+
+ auto b = lexicographical_compare_three_way(intArray1, intArray1 + 6, intArray2, intArray2 + 6, compare_strong);
+ EATEST_VERIFY(b == std::strong_ordering::less);
+ b = lexicographical_compare_three_way(intArray3, intArray3 + 5, intArray2, intArray2 + 6, compare_strong);
+ EATEST_VERIFY(b == std::strong_ordering::less);
+ b = lexicographical_compare_three_way(intArray3, intArray3 + 5, intArray2, intArray2 + 6, synth_three_way{});
+ EATEST_VERIFY(b == std::strong_ordering::less);
+
+ b = lexicographical_compare_three_way(intArray2, intArray2 + 6, intArray1, intArray1 + 6, compare_strong);
+ EATEST_VERIFY(b == std::strong_ordering::greater);
+ b = lexicographical_compare_three_way(intArray2, intArray2 + 6, intArray1, intArray1 + 6, synth_three_way{});
+ EATEST_VERIFY(b == std::strong_ordering::greater);
+
+ b = lexicographical_compare_three_way(intArray1, intArray1 + 6, intArray3, intArray3 + 5, compare_strong);
+ EATEST_VERIFY(b == std::strong_ordering::greater);
+ b = lexicographical_compare_three_way(intArray1, intArray1 + 6, intArray3, intArray3 + 5, synth_three_way{});
+ EATEST_VERIFY(b == std::strong_ordering::greater);
+
+ b = lexicographical_compare_three_way(intArray1, intArray1, intArray2, intArray2, compare_strong); // Test empty range.
+ EATEST_VERIFY(b == std::strong_ordering::equal);
+ b = lexicographical_compare_three_way(intArray1, intArray1, intArray2, intArray2, synth_three_way{}); // Test empty range.
+ EATEST_VERIFY(b == std::strong_ordering::equal);
+
+ // weak ordering
+ auto compare_weak = [](int first, int second)
+ {
+ return (first < second) ? std::weak_ordering::less :
+ (first > second) ? std::weak_ordering::greater :
+ std::weak_ordering::equivalent;
+ };
+
+ auto c = lexicographical_compare_three_way(intArray3, intArray3 + 5, intArray4, intArray4 + 5, compare_weak);
+ EATEST_VERIFY(c == std::weak_ordering::less);
+ c = lexicographical_compare_three_way(intArray4, intArray4 + 5, intArray3, intArray3 + 5, compare_weak);
+ EATEST_VERIFY(c == std::weak_ordering::greater);
+ c = lexicographical_compare_three_way(intArray3, intArray3 + 5, intArray4, intArray4 + 5, synth_three_way{});
+ EATEST_VERIFY(c == std::weak_ordering::less);
+ c = lexicographical_compare_three_way(intArray4, intArray4 + 5, intArray3, intArray3 + 5, synth_three_way{});
+ EATEST_VERIFY(c == std::weak_ordering::greater);
+ }
+
+ {
+ EATEST_VERIFY(synth_three_way{}(1, 1) == std::strong_ordering::equal);
+ EATEST_VERIFY(synth_three_way{}(2, 1) == std::strong_ordering::greater);
+ EATEST_VERIFY(synth_three_way{}(1, 2) == std::strong_ordering::less);
+
+ struct weak_struct
+ {
+ int val;
+ inline std::weak_ordering operator<=>(const weak_struct& b) const
+ {
+ return val <=> b.val;
+ }
+ };
+
+ EATEST_VERIFY(synth_three_way{}(weak_struct{1}, weak_struct{2}) == std::weak_ordering::less);
+ EATEST_VERIFY(synth_three_way{}(weak_struct{2}, weak_struct{1}) == std::weak_ordering::greater);
+ EATEST_VERIFY(synth_three_way{}(weak_struct{1}, weak_struct{1}) == std::weak_ordering::equivalent);
+ }
+#endif
{
// ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value)
@@ -1815,7 +1891,164 @@ int TestAlgorithm()
}
- {
+ {
+ // ForwardIterator apply_and_remove(ForwardIterator first, ForwardIterator last, Function function, const T&
+ // value) ForwardIterator apply_and_remove_if(ForwardIterator first, ForwardIterator last, Function function,
+ // Predicate predicate)
+
+ // Test for empty range and full container range
+ {
+ int intArray[12] = {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1};
+ vector<int> output;
+ auto func = [&output](int a) { output.push_back(a); };
+ int* pInt = apply_and_remove(intArray, intArray, func, 1);
+ EATEST_VERIFY(pInt == intArray);
+ EATEST_VERIFY(VerifySequence(intArray, intArray + 12, int(), "apply_and_remove", 0, 0, 1, 1, 0, 0, 1, 1, 0,
+ 0, 1, 1, -1));
+ EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), "apply_and_remove", -1));
+ pInt = apply_and_remove(intArray, intArray + 12, func, 1);
+ EATEST_VERIFY(pInt == intArray + 6);
+ EATEST_VERIFY(VerifySequence(intArray, intArray + 6, int(), "apply_and_remove", 0, 0, 0, 0, 0, 0, -1));
+ EATEST_VERIFY(
+ VerifySequence(output.begin(), output.end(), int(), "apply_and_remove", 1, 1, 1, 1, 1, 1, -1));
+ }
+
+ // Test for no match on empty range and full container range
+ {
+ int intArray[12] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3};
+ vector<int> output;
+ auto func = [&output](int a) { output.push_back(a); };
+ int* pInt = apply_and_remove(intArray, intArray, func, 1);
+ EATEST_VERIFY(pInt == intArray);
+ EATEST_VERIFY(VerifySequence(intArray, intArray + 12, int(), "apply_and_remove", 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, -1));
+ EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), "apply_and_remove", -1));
+ pInt = apply_and_remove(intArray, intArray + 12, func, 1);
+ EATEST_VERIFY(pInt == intArray + 12);
+ EATEST_VERIFY(VerifySequence(intArray, intArray + 12, int(), "apply_and_remove", 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, -1));
+ EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), "apply_and_remove", -1));
+ }
+
+ // Test for empty range and full container range
+ {
+ int intArray[12] = {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1};
+ vector<int> output;
+ auto func = [&output](int a) { output.push_back(a); };
+ int* pInt = apply_and_remove_if(intArray, intArray, func, bind2nd(equal_to<int>(), (int)1));
+ EATEST_VERIFY(pInt == intArray);
+ EATEST_VERIFY(VerifySequence(intArray, intArray + 12, int(), "apply_and_remove_if", 0, 0, 1, 1, 0, 0, 1, 1,
+ 0, 0, 1, 1, -1));
+ EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), "apply_and_remove_if", -1));
+ pInt = apply_and_remove_if(intArray, intArray + 12, func, bind2nd(equal_to<int>(), (int)1));
+ EATEST_VERIFY(pInt == intArray + 6);
+ EATEST_VERIFY(VerifySequence(intArray, intArray + 6, int(), "apply_and_remove_if", 0, 0, 0, 0, 0, 0, -1));
+ EATEST_VERIFY(
+ VerifySequence(output.begin(), output.end(), int(), "apply_and_remove_if", 1, 1, 1, 1, 1, 1, -1));
+ }
+
+ // Test for no match on empty range and full container range
+ {
+ int intArray[12] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3};
+ vector<int> output;
+ auto func = [&output](int a) { output.push_back(a); };
+ int* pInt = apply_and_remove_if(intArray, intArray, func, bind2nd(equal_to<int>(), (int)1));
+ EATEST_VERIFY(pInt == intArray);
+ EATEST_VERIFY(VerifySequence(intArray, intArray + 12, int(), "apply_and_remove_if", 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, -1));
+ EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), "apply_and_remove_if", -1));
+ pInt = apply_and_remove_if(intArray, intArray + 12, func, bind2nd(equal_to<int>(), (int)1));
+ EATEST_VERIFY(pInt == intArray + 12);
+ EATEST_VERIFY(VerifySequence(intArray, intArray + 12, int(), "apply_and_remove_if", 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, -1));
+ EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), "apply_and_remove_if", -1));
+ }
+
+ auto even = [](int a) { return (a % 2) == 0; };
+ // Test to verify that the remaining element have stable ordering
+ {
+ int intArray[12] = {7, 8, 2, 3, 4, 5, 6, 0, 1, 9, 10, 11};
+ vector<int> output;
+ auto func = [&output](int a) { output.push_back(a); };
+ int* pInt = apply_and_remove_if(intArray, intArray + 12, func, even);
+ EATEST_VERIFY(pInt == intArray + 6);
+ EATEST_VERIFY(VerifySequence(intArray, intArray + 6, int(), "apply_and_remove_if", 7, 3, 5, 1, 9, 11, -1));
+ EATEST_VERIFY(
+ VerifySequence(output.begin(), output.end(), int(), "apply_and_remove_if", 8, 2, 4, 6, 0, 10, -1));
+ }
+ {
+ int intArray[12] = {7, 8, 0, 0, 4, 5, 6, 0, 1, 9, 0, 11};
+ vector<int> output;
+ auto func = [&output](int a) { output.push_back(a); };
+ int* pInt = apply_and_remove(intArray, intArray + 12, func, 0);
+ EATEST_VERIFY(pInt == intArray + 8);
+ EATEST_VERIFY(
+ VerifySequence(intArray, intArray + 8, int(), "apply_and_remove", 7, 8, 4, 5, 6, 1, 9, 11, -1));
+ EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), "apply_and_remove", 0, 0, 0, 0, -1));
+ }
+
+ // Tests on a list (i.e. non-contiguous memory container)
+ {
+ list<int> intList = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+ vector<int> output;
+ auto func = [&output](int a) { output.push_back(a); };
+ auto listIter = apply_and_remove_if(intList.begin(), intList.begin(), func, even);
+ EATEST_VERIFY(listIter == intList.begin());
+ EATEST_VERIFY(VerifySequence(intList.begin(), intList.end(), int(), "apply_and_remove_if", 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, -1));
+ EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), "apply_and_remove_if", -1));
+ listIter = apply_and_remove_if(intList.begin(), intList.end(), func, even);
+ EATEST_VERIFY(listIter == next(intList.begin(), 6));
+ EATEST_VERIFY(
+ VerifySequence(intList.begin(), listIter, int(), "apply_and_remove_if", 1, 3, 5, 7, 9, 11, -1));
+ EATEST_VERIFY(
+ VerifySequence(output.begin(), output.end(), int(), "apply_and_remove_if", 0, 2, 4, 6, 8, 10, -1));
+ }
+ {
+ list<int> intList = {0, 4, 2, 3, 4, 5, 6, 4, 4, 4, 10, 11};
+ vector<int> output;
+ auto func = [&output](int a) { output.push_back(a); };
+ auto listIter = apply_and_remove(intList.begin(), intList.begin(), func, 4);
+ EATEST_VERIFY(listIter == intList.begin());
+ EATEST_VERIFY(VerifySequence(intList.begin(), intList.end(), int(), "apply_and_remove", 0, 4, 2, 3, 4, 5, 6,
+ 4, 4, 4, 10, 11, -1));
+ EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), "apply_and_remove", -1));
+ listIter = apply_and_remove(intList.begin(), intList.end(), func, 4);
+ EATEST_VERIFY(listIter == next(intList.begin(), 7));
+ EATEST_VERIFY(
+ VerifySequence(intList.begin(), listIter, int(), "apply_and_remove", 0, 2, 3, 5, 6, 10, 11, -1));
+ EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), "apply_and_remove", 4, 4, 4, 4, 4, -1));
+ }
+
+ // Tests on a part of a container
+ {
+ vector<int> intVector = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+ vector<int> output;
+ auto func = [&output](int a) { output.push_back(a); };
+ auto vectorIter = apply_and_remove_if(next(intVector.begin(), 3), prev(intVector.end(), 2), func, even);
+ EATEST_VERIFY(vectorIter == next(intVector.begin(), 7));
+ EATEST_VERIFY(
+ VerifySequence(intVector.begin(), vectorIter, int(), "apply_and_remove_if", 0, 1, 2, 3, 5, 7, 9, -1));
+ EATEST_VERIFY(
+ VerifySequence(prev(intVector.end(), 2), intVector.end(), int(), "apply_and_remove_if", 10, 11, -1));
+ EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), "apply_and_remove_if", 4, 6, 8, -1));
+ }
+ {
+ vector<int> intVector = {5, 1, 5, 3, 4, 5, 5, 7, 8, 5, 10, 5};
+ vector<int> output;
+ auto func = [&output](int a) { output.push_back(a); };
+ auto vectorIter = apply_and_remove(next(intVector.begin(), 2), prev(intVector.end(), 3), func, 5);
+ EATEST_VERIFY(vectorIter == next(intVector.begin(), 6));
+ EATEST_VERIFY(
+ VerifySequence(intVector.begin(), vectorIter, int(), "apply_and_remove", 5, 1, 3, 4, 7, 8, -1));
+ EATEST_VERIFY(
+ VerifySequence(prev(intVector.end(), 3), intVector.end(), int(), "apply_and_remove", 5, 10, 5, -1));
+ EATEST_VERIFY(VerifySequence(output.begin(), output.end(), int(), "apply_and_remove", 5, 5, 5, -1));
+ }
+ }
+
+
+ {
// OutputIterator replace_copy(InputIterator first, InputIterator last, OutputIterator result, const T& old_value, const T& new_value)
// OutputIterator replace_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate predicate, const T& new_value)
diff --git a/EASTL/test/source/TestAllocator.cpp b/EASTL/test/source/TestAllocator.cpp
index 8cfaadd..2a28c07 100644
--- a/EASTL/test/source/TestAllocator.cpp
+++ b/EASTL/test/source/TestAllocator.cpp
@@ -129,7 +129,6 @@ static int TestFixedAllocator()
typedef eastl::list<int, fixed_allocator_with_overflow> IntList;
typedef IntList::node_type IntListNode;
- IntList intList1;
const size_t kAlignOfIntListNode = EA_ALIGN_OF(IntListNode);
// ensure the fixed buffer contains the default value that will be replaced
@@ -140,6 +139,8 @@ static int TestFixedAllocator()
EATEST_VERIFY(buffer1[i].mValue == DEFAULT_VALUE);
}
+ IntList intList1;
+
// replace all the values in the local buffer with the test value
intList1.get_allocator().init(buffer1, sizeof(buffer1), sizeof(IntListNode), kAlignOfIntListNode);
for (size_t i = 0; i < kBufferCount; i++)
@@ -150,6 +151,8 @@ static int TestFixedAllocator()
{
EATEST_VERIFY(buffer1[i].mValue == TEST_VALUE);
}
+
+ intList1.clear();
}
{ // fixed_allocator_with_overflow
diff --git a/EASTL/test/source/TestArray.cpp b/EASTL/test/source/TestArray.cpp
index 3db95b9..ca05b67 100644
--- a/EASTL/test/source/TestArray.cpp
+++ b/EASTL/test/source/TestArray.cpp
@@ -125,6 +125,22 @@ int TestArray()
VERIFY(!(a >= c));
VERIFY(!(a > c));
+#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+ VERIFY( (a <=> b) == 0);
+ VERIFY(!((a <=> b) != 0));
+ VERIFY(!((a <=> b) < 0));
+ VERIFY( (a <=> b) <= 0);
+ VERIFY( (a <=> b) >= 0);
+ VERIFY(!((a <=> b) > 0));
+
+ VERIFY(!((a <=> c) == 0));
+ VERIFY( (a <=> c) != 0);
+ VERIFY( (a <=> c) < 0);
+ VERIFY( (a <=> c) <= 0);
+ VERIFY(!((a <=> c) >= 0));
+ VERIFY(!((a <=> c) > 0));
+#endif
+
// deduction guides
#ifdef __cpp_deduction_guides
array deduced {1,2,3,4,5};
@@ -132,6 +148,37 @@ int TestArray()
static_assert(eastl::is_same_v<decltype(deduced)::value_type, int>, "deduced array value_type mismatch");
VERIFY(deduced.size() == 5);
#endif
+
+ // structured binding
+
+ {
+ eastl::array<int, 5> aCopy = a;
+ auto&& [a0, a1, a2, a3, a4] = aCopy;
+
+ VERIFY(a0 == aCopy[0]);
+ VERIFY(a1 == aCopy[1]);
+ VERIFY(a2 == aCopy[2]);
+ VERIFY(a3 == aCopy[3]);
+ VERIFY(a4 == aCopy[4]);
+
+ a0 = 100;
+ VERIFY(aCopy[0] == 100);
+
+ a4 = 0;
+ VERIFY(aCopy[4] == 0);
+
+ // The deduced type may or may not be a reference type; it is an aliased type,
+ // as per https://en.cppreference.com/w/cpp/language/structured_binding:
+ // > Like a reference, a structured binding is an alias to an existing object. Unlike a reference,
+ // the type of a structured binding does not have to be a reference type.
+ // Any reference specifier is thus removed to check only the type & its const qualifier
+ static_assert(eastl::is_same_v<eastl::remove_reference_t<decltype(a0)>, int>);
+
+ const eastl::array<int, 5> aConstCopy = a;
+ auto&& [aConst0, aConst1, aConst2, aConst3, aConst4] = aConstCopy;
+
+ static_assert(eastl::is_same_v<eastl::remove_reference_t<decltype(aConst0)>, const int>);
+ }
}
// constexpr tests
diff --git a/EASTL/test/source/TestBitcast.cpp b/EASTL/test/source/TestBitcast.cpp
new file mode 100644
index 0000000..d6f0840
--- /dev/null
+++ b/EASTL/test/source/TestBitcast.cpp
@@ -0,0 +1,52 @@
+/////////////////////////////////////////////////////////////////////////////
+// Copyright (c) Electronic Arts Inc. All rights reserved.
+/////////////////////////////////////////////////////////////////////////////
+
+
+#include "EASTLTest.h"
+#include <EASTL/bit.h>
+
+using namespace eastl;
+
+
+int TestBitcast()
+{
+ int nErrorCount = 0;
+
+ {
+ uint32_t int32Value = 0x12345678;
+ float floatValue = eastl::bit_cast<float>(int32Value);
+ VERIFY(memcmp(&int32Value, &floatValue, sizeof(float)) == 0);
+ }
+
+ {
+ struct IntFloatStruct
+ {
+ uint32_t i = 0x87654321;
+ float f = 10.f;
+ };
+ struct CharIntStruct
+ {
+ char c1;
+ char c2;
+ char c3;
+ char c4;
+ uint32_t i;
+ };
+
+ IntFloatStruct ifStruct;
+ CharIntStruct ciStruct = eastl::bit_cast<CharIntStruct>(ifStruct);
+ VERIFY(memcmp(&ifStruct, &ciStruct, sizeof(IntFloatStruct)) == 0);
+ }
+
+#if EASTL_CONSTEXPR_BIT_CAST_SUPPORTED
+ {
+ constexpr uint32_t int32Value = 40;
+ constexpr float floatValue = eastl::bit_cast<float>(int32Value);
+ VERIFY(memcmp(&int32Value, &floatValue, sizeof(float)) == 0);
+ }
+#endif
+
+
+ return nErrorCount;
+}
diff --git a/EASTL/test/source/TestChrono.cpp b/EASTL/test/source/TestChrono.cpp
index 6a698e9..a56b934 100644
--- a/EASTL/test/source/TestChrono.cpp
+++ b/EASTL/test/source/TestChrono.cpp
@@ -89,12 +89,15 @@ int TestDuration()
microseconds us = 2 * ms; // 6000 microseconds constructed from 3 milliseconds
VERIFY(us.count() == 6000);
+
+ microseconds us2 = ms * 2; // 6000 microseconds constructed from 3 milliseconds
+ VERIFY(us2.count() == 6000);
- microseconds us2 = us / 2;
- VERIFY(us2.count() == 3000);
+ microseconds us3 = us / 2;
+ VERIFY(us3.count() == 3000);
- microseconds us3 = us % 2;
- VERIFY(us3.count() == 0);
+ microseconds us4 = us % 2;
+ VERIFY(us4.count() == 0);
}
}
diff --git a/EASTL/test/source/TestDeque.cpp b/EASTL/test/source/TestDeque.cpp
index 99076ff..e3f4ab6 100644
--- a/EASTL/test/source/TestDeque.cpp
+++ b/EASTL/test/source/TestDeque.cpp
@@ -1063,29 +1063,61 @@ int TestDeque()
{
eastl::deque<int> d = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- eastl::erase(d, 2);
+ auto numErased = eastl::erase(d, 2);
VERIFY((d == eastl::deque<int>{1, 3, 4, 5, 6, 7, 8, 9}));
+ VERIFY(numErased == 1);
- eastl::erase(d, 7);
+ numErased = eastl::erase(d, 7);
VERIFY((d == eastl::deque<int>{1, 3, 4, 5, 6, 8, 9}));
+ VERIFY(numErased == 1);
- eastl::erase(d, 9);
+ numErased = eastl::erase(d, 9);
VERIFY((d == eastl::deque<int>{1, 3, 4, 5, 6, 8}));
+ VERIFY(numErased == 1);
- eastl::erase(d, 5);
+ numErased = eastl::erase(d, 5);
VERIFY((d == eastl::deque<int>{1, 3, 4, 6, 8}));
+ VERIFY(numErased == 1);
- eastl::erase(d, 3);
+ numErased = eastl::erase(d, 3);
VERIFY((d == eastl::deque<int>{1, 4, 6, 8}));
+ VERIFY(numErased == 1);
}
{
eastl::deque<int> d = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- eastl::erase_if(d, [](auto i) { return i % 2 == 0; });
+ auto numErased = eastl::erase_if(d, [](auto i) { return i % 2 == 0; });
VERIFY((d == eastl::deque<int>{1, 3, 5, 7, 9}));
+ VERIFY(numErased == 4);
}
}
+#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+
+ { // Test <=>
+ eastl::deque<int> d1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ eastl::deque<int> d2 = {9, 8, 7, 6, 5, 4, 3, 2, 1};
+ eastl::deque<int> d3 = {1, 2, 3, 4, 5};
+ eastl::deque<int> d4 = {10};
+
+ VERIFY(d1 != d2);
+ VERIFY(d1 < d2);
+ VERIFY(d1 != d3);
+ VERIFY(d1 > d3);
+ VERIFY(d4 > d1);
+ VERIFY(d4 > d2);
+ VERIFY(d4 > d3);
+
+ VERIFY((d1 <=> d2) != 0);
+ VERIFY((d1 <=> d2) < 0);
+ VERIFY((d1 <=> d3) != 0);
+ VERIFY((d1 <=> d3) > 0);
+ VERIFY((d4 <=> d1) > 0);
+ VERIFY((d4 <=> d2) > 0);
+ VERIFY((d4 <=> d3) > 0);
+ }
+#endif
+
return nErrorCount;
}
diff --git a/EASTL/test/source/TestExtra.cpp b/EASTL/test/source/TestExtra.cpp
index 03f7b41..52fbd62 100644
--- a/EASTL/test/source/TestExtra.cpp
+++ b/EASTL/test/source/TestExtra.cpp
@@ -66,6 +66,7 @@ namespace eastl
#include <EASTL/string.h>
#include <EASTL/hash_set.h>
#include <EASTL/random.h>
+#include <EASTL/bit.h>
#include <EASTL/core_allocator_adapter.h>
#include <EASTL/bonus/call_traits.h>
#include <EASTL/bonus/compressed_pair.h>
@@ -292,7 +293,6 @@ static int TestQueue()
EATEST_VERIFY(!(toListQueue < toListQueue2));
EATEST_VERIFY(!(toListQueue > toListQueue2));
-
// bool empty() const;
// size_type size() const;
EATEST_VERIFY(toListQueue.empty());
@@ -356,6 +356,103 @@ static int TestQueue()
EATEST_VERIFY(intQueue.front() == 5);
}
+#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+ {
+ // queue(const Sequence& x = Sequence());
+ queue<TestObject, list<TestObject>> toListQueue;
+ queue<TestObject, list<TestObject>> toListQueue2;
+
+
+ // global operators
+ EATEST_VERIFY( ((toListQueue <=> toListQueue2) == 0));
+ EATEST_VERIFY(!((toListQueue <=> toListQueue2) != 0));
+ EATEST_VERIFY( ((toListQueue <=> toListQueue2) <= 0));
+ EATEST_VERIFY( ((toListQueue <=> toListQueue2) >= 0));
+ EATEST_VERIFY(!((toListQueue <=> toListQueue2) < 0));
+ EATEST_VERIFY(!((toListQueue <=> toListQueue2) > 0));
+
+ // bool empty() const;
+ // size_type size() const;
+ EATEST_VERIFY(toListQueue.empty());
+ EATEST_VERIFY(toListQueue.size() == 0);
+
+ // Verify toListQueue > toListQueue2
+ toListQueue.push(TestObject(0));
+ toListQueue.push(TestObject(1));
+ toListQueue2.push(TestObject(0));
+
+ EATEST_VERIFY(!((toListQueue <=> toListQueue2) == 0));
+ EATEST_VERIFY( ((toListQueue <=> toListQueue2) != 0));
+ EATEST_VERIFY( ((toListQueue <=> toListQueue2) >= 0));
+ EATEST_VERIFY(!((toListQueue <=> toListQueue2) <= 0));
+ EATEST_VERIFY( ((toListQueue <=> toListQueue2) > 0));
+ EATEST_VERIFY(!((toListQueue <=> toListQueue2) < 0));
+
+ // Verify toListQueue2 > toListQueue by element size
+ toListQueue2.push(TestObject(3));
+ EATEST_VERIFY(!((toListQueue <=> toListQueue2) == 0));
+ EATEST_VERIFY( ((toListQueue <=> toListQueue2) != 0));
+ EATEST_VERIFY( ((toListQueue <=> toListQueue2) <= 0));
+ EATEST_VERIFY(!((toListQueue <=> toListQueue2) >= 0));
+ EATEST_VERIFY( ((toListQueue <=> toListQueue2) < 0));
+ EATEST_VERIFY(!((toListQueue <=> toListQueue2) > 0));
+
+ queue<TestObject, list<TestObject>> toListQueue3;
+ queue<TestObject, list<TestObject>> toListQueue4;
+
+ for (int i = 0; i < 10; i++)
+ {
+ toListQueue3.push(TestObject(i));
+ if (i < 5)
+ toListQueue4.push(TestObject(i));
+ }
+
+ // Verify toListQueue4 is a strict subset of toListQueue3
+ EATEST_VERIFY(!((toListQueue3 <=> toListQueue4) == 0));
+ EATEST_VERIFY( ((toListQueue3 <=> toListQueue4) != 0));
+ EATEST_VERIFY( ((toListQueue3 <=> toListQueue4) >= 0));
+ EATEST_VERIFY(!((toListQueue3 <=> toListQueue4) <= 0));
+ EATEST_VERIFY( ((toListQueue3 <=> toListQueue4) > 0));
+ EATEST_VERIFY(!((toListQueue3 <=> toListQueue4) < 0));
+
+ // Verify that even thoughn toListQueue4 has a smaller size, it's lexicographically larger
+ toListQueue4.push(TestObject(11));
+ EATEST_VERIFY(!((toListQueue3 <=> toListQueue4) == 0));
+ EATEST_VERIFY( ((toListQueue3 <=> toListQueue4) != 0));
+ EATEST_VERIFY( ((toListQueue3 <=> toListQueue4) <= 0));
+ EATEST_VERIFY(!((toListQueue3 <=> toListQueue4) >= 0));
+ EATEST_VERIFY( ((toListQueue3 <=> toListQueue4) < 0));
+ EATEST_VERIFY(!((toListQueue3 <=> toListQueue4) > 0));
+
+ }
+
+ {
+ queue<TestObject, list<TestObject>> toListQueue1;
+ queue<TestObject, list<TestObject>> toListQueue2;
+ queue<TestObject, list<TestObject>> toListQueue3;
+
+ for (int i = 0; i < 10; i++)
+ {
+ toListQueue1.push(TestObject(i));
+ toListQueue2.push(TestObject(9-i));
+ if (i < 5)
+ toListQueue3.push(TestObject(i));
+ }
+
+ struct weak_ordering_queue
+ {
+ queue<TestObject, list<TestObject>> queue;
+ inline std::weak_ordering operator<=>(const weak_ordering_queue& b) const { return queue <=> b.queue; }
+ };
+
+ EATEST_VERIFY(synth_three_way{}(weak_ordering_queue{toListQueue1}, weak_ordering_queue{toListQueue2}) == std::weak_ordering::less);
+ EATEST_VERIFY(synth_three_way{}(weak_ordering_queue{toListQueue3}, weak_ordering_queue{toListQueue1}) == std::weak_ordering::less);
+ EATEST_VERIFY(synth_three_way{}(weak_ordering_queue{toListQueue2}, weak_ordering_queue{toListQueue1}) == std::weak_ordering::greater);
+ EATEST_VERIFY(synth_three_way{}(weak_ordering_queue{toListQueue2}, weak_ordering_queue{toListQueue3}) == std::weak_ordering::greater);
+ EATEST_VERIFY(synth_three_way{}(weak_ordering_queue{toListQueue1}, weak_ordering_queue{toListQueue1}) == std::weak_ordering::equivalent);
+ }
+ #endif
+
{
vector<TestObject> toVector;
for(int i = 0; i < 100; i++)
@@ -620,7 +717,6 @@ static int TestStack()
EATEST_VERIFY(!(toListStack < toListStack2));
EATEST_VERIFY(!(toListStack > toListStack2));
-
// void push(const value_type& value);
// reference top();
// const_reference top() const;
@@ -665,6 +761,101 @@ static int TestStack()
#endif
}
+#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+ {
+ // stack(const Sequence& x = Sequence());
+ stack<TestObject, list<TestObject> > toListStack;
+ stack<TestObject, list<TestObject> > toListStack2;
+
+ // bool empty() const;
+ // size_type size() const;
+ EATEST_VERIFY(toListStack.empty());
+ EATEST_VERIFY(toListStack.size() == 0);
+
+
+ // global operators
+ EATEST_VERIFY( ((toListStack <=> toListStack2) == 0));
+ EATEST_VERIFY(!((toListStack <=> toListStack2) != 0));
+ EATEST_VERIFY( ((toListStack <=> toListStack2) <= 0));
+ EATEST_VERIFY( ((toListStack <=> toListStack2) >= 0));
+ EATEST_VERIFY(!((toListStack <=> toListStack2) < 0));
+ EATEST_VERIFY(!((toListStack <=> toListStack2) > 0));
+
+ toListStack.push(TestObject(0));
+ toListStack.push(TestObject(1));
+ toListStack2.push(TestObject(0));
+
+ EATEST_VERIFY(!((toListStack <=> toListStack2) == 0));
+ EATEST_VERIFY( ((toListStack <=> toListStack2) != 0));
+ EATEST_VERIFY( ((toListStack <=> toListStack2) >= 0));
+ EATEST_VERIFY(!((toListStack <=> toListStack2) <= 0));
+ EATEST_VERIFY( ((toListStack <=> toListStack2) > 0));
+ EATEST_VERIFY(!((toListStack <=> toListStack2) < 0));
+
+ // Verify toListStack2 > toListStack by element size
+ toListStack2.push(TestObject(3));
+ EATEST_VERIFY(!((toListStack <=> toListStack2) == 0));
+ EATEST_VERIFY( ((toListStack <=> toListStack2) != 0));
+ EATEST_VERIFY( ((toListStack <=> toListStack2) <= 0));
+ EATEST_VERIFY(!((toListStack <=> toListStack2) >= 0));
+ EATEST_VERIFY( ((toListStack <=> toListStack2) < 0));
+ EATEST_VERIFY(!((toListStack <=> toListStack2) > 0));
+
+ stack<TestObject, list<TestObject> > toListStack3;
+ stack<TestObject, list<TestObject> > toListStack4;
+
+ for (int i = 0; i < 10; i++)
+ {
+ toListStack3.push(TestObject(i));
+ if (i < 5)
+ toListStack4.push(TestObject(i));
+ }
+
+ // Verify toListStack4 is a strict subset of toListStack3
+ EATEST_VERIFY(!((toListStack3 <=> toListStack4) == 0));
+ EATEST_VERIFY( ((toListStack3 <=> toListStack4) != 0));
+ EATEST_VERIFY( ((toListStack3 <=> toListStack4) >= 0));
+ EATEST_VERIFY(!((toListStack3 <=> toListStack4) <= 0));
+ EATEST_VERIFY( ((toListStack3 <=> toListStack4) > 0));
+ EATEST_VERIFY(!((toListStack3 <=> toListStack4) < 0));
+
+ // Verify that even thoughn toListQueue4 has a smaller size, it's lexicographically larger
+ toListStack4.push(TestObject(11));
+ EATEST_VERIFY(!((toListStack3 <=> toListStack4) == 0));
+ EATEST_VERIFY( ((toListStack3 <=> toListStack4) != 0));
+ EATEST_VERIFY( ((toListStack3 <=> toListStack4) <= 0));
+ EATEST_VERIFY(!((toListStack3 <=> toListStack4) >= 0));
+ EATEST_VERIFY( ((toListStack3 <=> toListStack4) < 0));
+ EATEST_VERIFY(!((toListStack3 <=> toListStack4) > 0));
+ }
+
+ {
+ stack<TestObject, list<TestObject> > toListStack1;
+ stack<TestObject, list<TestObject> > toListStack2;
+ stack<TestObject, list<TestObject> > toListStack3;
+
+ for (int i = 0; i < 10; i++)
+ {
+ toListStack1.push(TestObject(i));
+ toListStack2.push(TestObject(9-i));
+ if (i < 5)
+ toListStack3.push(TestObject(i));
+ }
+
+ struct weak_ordering_stack
+ {
+ stack<TestObject, list<TestObject> > stack;
+ inline std::weak_ordering operator<=>(const weak_ordering_stack& b) const { return stack <=> b.stack; }
+ };
+
+ EATEST_VERIFY(synth_three_way{}(weak_ordering_stack{toListStack1}, weak_ordering_stack{toListStack2}) == std::weak_ordering::less);
+ EATEST_VERIFY(synth_three_way{}(weak_ordering_stack{toListStack3}, weak_ordering_stack{toListStack1}) == std::weak_ordering::less);
+ EATEST_VERIFY(synth_three_way{}(weak_ordering_stack{toListStack2}, weak_ordering_stack{toListStack1}) == std::weak_ordering::greater);
+ EATEST_VERIFY(synth_three_way{}(weak_ordering_stack{toListStack2}, weak_ordering_stack{toListStack3}) == std::weak_ordering::greater);
+ EATEST_VERIFY(synth_three_way{}(weak_ordering_stack{toListStack1}, weak_ordering_stack{toListStack1}) == std::weak_ordering::equivalent);
+ }
+#endif
+
{
vector<TestObject> toVector;
@@ -862,6 +1053,281 @@ static int TestNumeric()
return nErrorCount;
}
+#if defined(EA_COMPILER_CPP20_ENABLED)
+template <typename T>
+static constexpr int SignedIntMidpoint()
+{
+ int nErrorCount = 0;
+
+ EATEST_VERIFY(eastl::midpoint(T(0), T(0)) == T(0));
+ EATEST_VERIFY(eastl::midpoint(T(0), T(2)) == T(1));
+ EATEST_VERIFY(eastl::midpoint(T(0), T(4)) == T(2));
+ EATEST_VERIFY(eastl::midpoint(T(0), T(8)) == T(4));
+ EATEST_VERIFY(eastl::midpoint(T(2), T(0)) == T(1));
+ EATEST_VERIFY(eastl::midpoint(T(4), T(0)) == T(2));
+ EATEST_VERIFY(eastl::midpoint(T(8), T(0)) == T(4));
+
+ EATEST_VERIFY(eastl::midpoint(T(1), T(1)) == T(1));
+ EATEST_VERIFY(eastl::midpoint(T(1), T(3)) == T(2));
+ EATEST_VERIFY(eastl::midpoint(T(3), T(1)) == T(2));
+ EATEST_VERIFY(eastl::midpoint(T(2), T(6)) == T(4));
+ EATEST_VERIFY(eastl::midpoint(T(6), T(2)) == T(4));
+
+ EATEST_VERIFY(eastl::midpoint(T(-1), T(-1)) == T(-1));
+ EATEST_VERIFY(eastl::midpoint(T(-1), T(-3)) == T(-2));
+ EATEST_VERIFY(eastl::midpoint(T(-3), T(-1)) == T(-2));
+ EATEST_VERIFY(eastl::midpoint(T(-2), T(-6)) == T(-4));
+ EATEST_VERIFY(eastl::midpoint(T(-6), T(-2)) == T(-4));
+
+ EATEST_VERIFY(eastl::midpoint(T(-0), T(0)) == T(0));
+ EATEST_VERIFY(eastl::midpoint(T(0), T(-0)) == T(0));
+ EATEST_VERIFY(eastl::midpoint(T(-0), T(-0)) == T(0));
+ EATEST_VERIFY(eastl::midpoint(T(-1), T(1)) == T(0));
+ EATEST_VERIFY(eastl::midpoint(T(-10), T(10)) == T(0));
+ EATEST_VERIFY(eastl::midpoint(T(-3), T(7)) == T(2));
+ EATEST_VERIFY(eastl::midpoint(T(-7), T(3)) == T(-2));
+ EATEST_VERIFY(eastl::midpoint(T(-2), T(6)) == T(2));
+ EATEST_VERIFY(eastl::midpoint(T(-6), T(2)) == T(-2));
+ EATEST_VERIFY(eastl::midpoint(T(2), T(-6)) == T(-2));
+ EATEST_VERIFY(eastl::midpoint(T(6), T(-2)) == T(2));
+
+ // If an odd sum, midpoint should round towards the LHS operand.
+ EATEST_VERIFY(eastl::midpoint(T(0), T(5)) == T(2));
+ EATEST_VERIFY(eastl::midpoint(T(5), T(0)) == T(3));
+ EATEST_VERIFY(eastl::midpoint(T(1), T(4)) == T(2));
+ EATEST_VERIFY(eastl::midpoint(T(4), T(1)) == T(3));
+ EATEST_VERIFY(eastl::midpoint(T(7), T(10)) == T(8));
+ EATEST_VERIFY(eastl::midpoint(T(10), T(7)) == T(9));
+ EATEST_VERIFY(eastl::midpoint(T(-1), T(2)) == T(0));
+ EATEST_VERIFY(eastl::midpoint(T(2), T(-1)) == T(1));
+ EATEST_VERIFY(eastl::midpoint(T(-5), T(4)) == T(-1));
+ EATEST_VERIFY(eastl::midpoint(T(4), T(-5)) == T(0));
+
+ // Test absolute limits
+ constexpr T MIN = eastl::numeric_limits<T>::min();
+ constexpr T MAX = eastl::numeric_limits<T>::max();
+
+ EATEST_VERIFY(eastl::midpoint(MIN, MIN) == MIN);
+ EATEST_VERIFY(eastl::midpoint(MAX, MAX) == MAX);
+ EATEST_VERIFY(eastl::midpoint(MIN, MAX) == T(-1));
+ EATEST_VERIFY(eastl::midpoint(MAX, MIN) == T(0));
+ EATEST_VERIFY(eastl::midpoint(MIN, T(0)) == MIN / 2);
+ EATEST_VERIFY(eastl::midpoint(T(0), MIN) == MIN / 2);
+ EATEST_VERIFY(eastl::midpoint(MAX, T(0)) == (MAX / 2) + 1);
+ EATEST_VERIFY(eastl::midpoint(T(0), MAX) == (MAX / 2));
+
+ EATEST_VERIFY(eastl::midpoint(MIN, T(10)) == (MIN / 2) + 5);
+ EATEST_VERIFY(eastl::midpoint(T(10), MIN) == (MIN / 2) + 5);
+ EATEST_VERIFY(eastl::midpoint(MAX, T(10)) == (MAX / 2) + 5 + 1);
+ EATEST_VERIFY(eastl::midpoint(T(10), MAX) == (MAX / 2) + 5);
+ EATEST_VERIFY(eastl::midpoint(MIN, T(-10)) == (MIN / 2) - 5);
+ EATEST_VERIFY(eastl::midpoint(T(-10), MIN) == (MIN / 2) - 5);
+ EATEST_VERIFY(eastl::midpoint(MAX, T(-10)) == (MAX / 2) - 5 + 1);
+ EATEST_VERIFY(eastl::midpoint(T(-10), MAX) == (MAX / 2) - 5);
+
+ return nErrorCount;
+}
+
+template <typename T>
+static constexpr int UnsignedIntMidpoint()
+{
+ int nErrorCount = 0;
+
+ EATEST_VERIFY(eastl::midpoint(T(0), T(0)) == T(0));
+ EATEST_VERIFY(eastl::midpoint(T(0), T(2)) == T(1));
+ EATEST_VERIFY(eastl::midpoint(T(0), T(4)) == T(2));
+ EATEST_VERIFY(eastl::midpoint(T(0), T(8)) == T(4));
+ EATEST_VERIFY(eastl::midpoint(T(2), T(0)) == T(1));
+ EATEST_VERIFY(eastl::midpoint(T(4), T(0)) == T(2));
+ EATEST_VERIFY(eastl::midpoint(T(8), T(0)) == T(4));
+
+ EATEST_VERIFY(eastl::midpoint(T(1), T(1)) == T(1));
+ EATEST_VERIFY(eastl::midpoint(T(1), T(3)) == T(2));
+ EATEST_VERIFY(eastl::midpoint(T(3), T(1)) == T(2));
+ EATEST_VERIFY(eastl::midpoint(T(2), T(6)) == T(4));
+ EATEST_VERIFY(eastl::midpoint(T(6), T(2)) == T(4));
+
+ // If an odd sum, midpoint should round towards the LHS operand.
+ EATEST_VERIFY(eastl::midpoint(T(0), T(5)) == T(2));
+ EATEST_VERIFY(eastl::midpoint(T(5), T(0)) == T(3));
+ EATEST_VERIFY(eastl::midpoint(T(1), T(4)) == T(2));
+ EATEST_VERIFY(eastl::midpoint(T(4), T(1)) == T(3));
+ EATEST_VERIFY(eastl::midpoint(T(7), T(10)) == T(8));
+ EATEST_VERIFY(eastl::midpoint(T(10), T(7)) == T(9));
+
+ // Test absolute limits
+ constexpr T MIN = eastl::numeric_limits<T>::min();
+ constexpr T MAX = eastl::numeric_limits<T>::max();
+
+ EATEST_VERIFY(eastl::midpoint(MIN, MIN) == MIN);
+ EATEST_VERIFY(eastl::midpoint(MAX, MAX) == MAX);
+ EATEST_VERIFY(eastl::midpoint(MIN, MAX) == MAX / 2);
+ EATEST_VERIFY(eastl::midpoint(MAX, MIN) == (MAX / 2) + 1);
+ EATEST_VERIFY(eastl::midpoint(MIN, T(0)) == T(0));
+ EATEST_VERIFY(eastl::midpoint(T(0), MIN) == T(0));
+
+ EATEST_VERIFY(eastl::midpoint(MIN, T(10)) == (MIN / 2) + 5);
+ EATEST_VERIFY(eastl::midpoint(T(10), MIN) == (MIN / 2) + 5);
+ EATEST_VERIFY(eastl::midpoint(MAX, T(10)) == (MAX / 2) + 5 + 1);
+ EATEST_VERIFY(eastl::midpoint(T(10), MAX) == (MAX / 2) + 5);
+
+ return nErrorCount;
+}
+
+template <typename T>
+static constexpr int FloatMidpoint()
+{
+ // for use with floats, double, long doubles.
+ int nErrorCount = 0;
+ EATEST_VERIFY(eastl::midpoint(T(0.0), T(0.0)) == T(0.0));
+ EATEST_VERIFY(eastl::midpoint(T(0.0), T(2.0)) == T(1.0));
+ EATEST_VERIFY(eastl::midpoint(T(0.0), T(4.0)) == T(2.0));
+ EATEST_VERIFY(eastl::midpoint(T(2.0), T(0.0)) == T(1.0));
+ EATEST_VERIFY(eastl::midpoint(T(4.0), T(0.0)) == T(2.0));
+
+ EATEST_VERIFY(eastl::midpoint(T(0.5), T(0.5)) == T(0.5));
+ EATEST_VERIFY(eastl::midpoint(T(0.0), T(0.5)) == T(0.25));
+ EATEST_VERIFY(eastl::midpoint(T(0.5), T(0.0)) == T(0.25));
+ EATEST_VERIFY(eastl::midpoint(T(0.5), T(1.0)) == T(0.75));
+ EATEST_VERIFY(eastl::midpoint(T(1.0), T(0.5)) == T(0.75));
+
+ EATEST_VERIFY(eastl::midpoint(T(-0.0), T(0.0)) == T(0.0));
+ EATEST_VERIFY(eastl::midpoint(T(0.0), T(-0.0)) == T(0.0));
+ EATEST_VERIFY(eastl::midpoint(T(-0.0), T(-0.0)) == T(0.0));
+ EATEST_VERIFY(eastl::midpoint(T(-1.0), T(2.0)) == T(0.5));
+ EATEST_VERIFY(eastl::midpoint(T(-2.0), T(1)) == T(-0.5));
+ EATEST_VERIFY(eastl::midpoint(T(-3.0), T(6.0)) == T(1.5));
+ EATEST_VERIFY(eastl::midpoint(T(-6.0), T(3.0)) == T(-1.5));
+
+ // Test absolute limits
+ const T MIN = eastl::numeric_limits<T>::min();
+ const T MAX = eastl::numeric_limits<T>::max();
+
+ EATEST_VERIFY(eastl::midpoint(MIN, MIN) == MIN);
+ EATEST_VERIFY(eastl::midpoint(MAX, MAX) == MAX);
+ EATEST_VERIFY(eastl::midpoint(MIN, MAX) == MAX / 2);
+ EATEST_VERIFY(eastl::midpoint(MAX, MIN) == MAX / 2);
+ EATEST_VERIFY(eastl::midpoint(-MAX, MIN) == -MAX / 2);
+
+ EATEST_VERIFY(eastl::midpoint(MIN, T(9.0)) == T(4.5));
+ EATEST_VERIFY(eastl::midpoint(MIN, T(-9.0)) == T(-4.5));
+ EATEST_VERIFY(eastl::midpoint(T(9.0), MIN) == T(4.5));
+ EATEST_VERIFY(eastl::midpoint(T(-9.0), MIN) == T(-4.5));
+ EATEST_VERIFY(eastl::midpoint(MAX, T(9.0)) == MAX / 2 + T(4.5));
+ EATEST_VERIFY(eastl::midpoint(MAX, T(-9.0)) == MAX / 2 - T(4.5));
+ EATEST_VERIFY(eastl::midpoint(T(9.0), MAX) == MAX / 2 + T(4.5));
+ EATEST_VERIFY(eastl::midpoint(T(-9.0), MAX) == MAX / 2 - T(4.5));
+
+ return nErrorCount;
+}
+
+template <typename T>
+static constexpr int PointerMidpoint()
+{
+ int nErrorCount = 0;
+
+ const T ARR[100] = {};
+
+ EATEST_VERIFY(eastl::midpoint(ARR, ARR) == ARR);
+ EATEST_VERIFY(eastl::midpoint(ARR, ARR + 100) == ARR + 50);
+ EATEST_VERIFY(eastl::midpoint(ARR + 100, ARR) == ARR + 50);
+ EATEST_VERIFY(eastl::midpoint(ARR, ARR + 25) == ARR + 12);
+ EATEST_VERIFY(eastl::midpoint(ARR + 25, ARR) == ARR + 13);
+ EATEST_VERIFY(eastl::midpoint(ARR, ARR + 13) == ARR + 6);
+ EATEST_VERIFY(eastl::midpoint(ARR + 13, ARR) == ARR + 7);
+ EATEST_VERIFY(eastl::midpoint(ARR + 50, ARR + 100) == ARR + 75);
+ EATEST_VERIFY(eastl::midpoint(ARR + 100, ARR + 50) == ARR + 75);
+
+ return nErrorCount;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// TestMidpoint
+//
+static int TestMidpoint()
+{
+ int nErrorCount = 0;
+
+ // template <typename T>
+ // constexpr eastl::enable_if_t<eastl::is_arithmetic_v<T> && !eastl::is_same_v<eastl::remove_cv_t<T>, bool>, T>
+ // midpoint(const T lhs, const T rhs) EA_NOEXCEPT
+ nErrorCount += SignedIntMidpoint<int>();
+ nErrorCount += SignedIntMidpoint<char>();
+ nErrorCount += SignedIntMidpoint<short>();
+ nErrorCount += SignedIntMidpoint<long>();
+ nErrorCount += SignedIntMidpoint<long long>();
+
+ nErrorCount += UnsignedIntMidpoint<unsigned int>();
+ nErrorCount += UnsignedIntMidpoint<unsigned char>();
+ nErrorCount += UnsignedIntMidpoint<unsigned short>();
+ nErrorCount += UnsignedIntMidpoint<unsigned long>();
+ nErrorCount += UnsignedIntMidpoint<unsigned long long>();
+
+ nErrorCount += FloatMidpoint<float>();
+ nErrorCount += FloatMidpoint<double>();
+ nErrorCount += FloatMidpoint<long double>();
+
+ // template <typename T>
+ // constexpr eastl::enable_if_t<eastl::is_object_v<T>, const T*> midpoint(const T* lhs, const T* rhs)
+ nErrorCount += PointerMidpoint<int>();
+ nErrorCount += PointerMidpoint<char>();
+ nErrorCount += PointerMidpoint<short>();
+ nErrorCount += PointerMidpoint<float>();
+ nErrorCount += PointerMidpoint<double>();
+ nErrorCount += PointerMidpoint<long double>();
+
+ return nErrorCount;
+}
+
+
+template <typename T>
+static constexpr int FloatLerp()
+{
+ int nErrorCount = 0;
+
+ EATEST_VERIFY(eastl::lerp(T(0.0), T(0.0), T(0.0)) == T(0.0));
+ EATEST_VERIFY(eastl::lerp(T(1.0), T(0.0), T(0.0)) == T(1.0));
+ EATEST_VERIFY(eastl::lerp(T(-1.0), T(0.0), T(0.0)) == T(-1.0));
+ EATEST_VERIFY(eastl::lerp(T(0.0), T(1.0), T(0.0)) == T(0.0));
+ EATEST_VERIFY(eastl::lerp(T(0.0), T(-1.0), T(0.0)) == T(0.0));
+ EATEST_VERIFY(eastl::lerp(T(-1.0), T(1.0), T(1.0)) == T(1.0));
+ EATEST_VERIFY(eastl::lerp(T(1.0), T(-1.0), T(1.0)) == T(-1.0));
+ EATEST_VERIFY(eastl::lerp(T(-1.0), T(1.0), T(0.5)) == T(0.0));
+ EATEST_VERIFY(eastl::lerp(T(1.0), T(-1.0), T(0.5)) == T(0.0));
+ EATEST_VERIFY(eastl::lerp(T(5.0), T(5.0), T(0.5)) == T(5.0));
+ EATEST_VERIFY(eastl::lerp(T(-5.0), T(-5.0), T(0.5)) == T(-5.0));
+ EATEST_VERIFY(eastl::lerp(T(1.0), T(2.0), T(1.0)) == T(2.0));
+ EATEST_VERIFY(eastl::lerp(T(2.0), T(1.0), T(1.0)) == T(1.0));
+ EATEST_VERIFY(eastl::lerp(T(1.0), T(2.0), T(1.0)) == T(2.0));
+ EATEST_VERIFY(eastl::lerp(T(1.0), T(2.0), T(2.0)) == T(3.0));
+ EATEST_VERIFY(eastl::lerp(T(2.0), T(1.0), T(2.0)) == T(0.0));
+ EATEST_VERIFY(eastl::lerp(T(1.0), T(-2.0), T(2.0)) == T(-5.0));
+ EATEST_VERIFY(eastl::lerp(T(-1.0), T(2.0), T(2.0)) == T(5.0));
+ EATEST_VERIFY(eastl::lerp(T(-1.5), T(1.5), T(0.75)) == T(0.75));
+ EATEST_VERIFY(eastl::lerp(T(0.125), T(1.75), T(0.25)) == T(0.53125));
+ EATEST_VERIFY(eastl::lerp(T(-0.125), T(-1.75), T(0.5)) == T(-0.9375));
+ EATEST_VERIFY(eastl::lerp(T(-0.125), T(1.5), T(2.5)) == T(3.9375));
+
+ return nErrorCount;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// TestLerp
+//
+static int TestLerp()
+{
+ int nErrorCount = 0;
+
+ // template <class T>
+ // constexpr T lerp(const T a, const T b, const T t) EA_NOEXCEPT
+ nErrorCount += FloatLerp<float>();
+ nErrorCount += FloatLerp<double>();
+ nErrorCount += FloatLerp<long double>();
+
+ return nErrorCount;
+}
+#endif
///////////////////////////////////////////////////////////////////////////////
@@ -914,7 +1380,142 @@ static int TestAdaptors()
return nErrorCount;
}
+#if defined(EA_COMPILER_CPP20_ENABLED)
+template <typename T>
+int TestHasSingleBit()
+{
+ int nErrorCount = 0;
+
+ VERIFY(eastl::has_single_bit(T(0)) == false);
+ VERIFY(eastl::has_single_bit(T(1)) == true);
+ VERIFY(eastl::has_single_bit(T(2)) == true);
+ VERIFY(eastl::has_single_bit(T(3)) == false);
+
+ VERIFY(eastl::has_single_bit(eastl::numeric_limits<T>::min()) == false);
+ VERIFY(eastl::has_single_bit(eastl::numeric_limits<T>::max()) == false);
+ for (int i = 4; i < eastl::numeric_limits<T>::digits; i++)
+ {
+ T power_of_two = static_cast<T>(T(1U) << i);
+ VERIFY(eastl::has_single_bit(power_of_two));
+ VERIFY(eastl::has_single_bit(static_cast<T>(power_of_two - 1)) == false);
+ }
+
+ return nErrorCount;
+}
+
+template <typename T>
+static int TestBitCeil()
+{
+ int nErrorCount = 0;
+
+ VERIFY(eastl::bit_ceil(T(0)) == T(1));
+ VERIFY(eastl::bit_ceil(T(1)) == T(1));
+ VERIFY(eastl::bit_ceil(T(2)) == T(2));
+ VERIFY(eastl::bit_ceil(T(3)) == T(4));
+
+ EA_CONSTEXPR auto DIGITS = eastl::numeric_limits<T>::digits;
+ EA_CONSTEXPR auto MIN = eastl::numeric_limits<T>::min();
+ EA_CONSTEXPR auto MAX = static_cast<T>(T(1) << (DIGITS - 1));
+
+ VERIFY(eastl::bit_ceil(MAX) == MAX);
+ VERIFY(eastl::bit_ceil(static_cast<T>(MAX - 1)) == MAX);
+ VERIFY(eastl::bit_ceil(MIN) == T(1));
+
+ for (int i = 4; i < eastl::numeric_limits<T>::digits; i++)
+ {
+ T power_of_two = static_cast<T>(T(1U) << i);
+ VERIFY(eastl::bit_ceil(power_of_two) == power_of_two);
+ VERIFY(eastl::bit_ceil(static_cast<T>(power_of_two - 1)) == power_of_two);
+ }
+
+ return nErrorCount;
+}
+
+template <typename T>
+static int TestBitFloor()
+{
+ int nErrorCount = 0;
+ VERIFY(eastl::bit_floor(T(0)) == T(0));
+ VERIFY(eastl::bit_floor(T(1)) == T(1));
+ VERIFY(eastl::bit_floor(T(2)) == T(2));
+ VERIFY(eastl::bit_floor(T(3)) == T(2));
+
+ EA_CONSTEXPR auto DIGITS = eastl::numeric_limits<T>::digits;
+ EA_CONSTEXPR auto MIN = eastl::numeric_limits<T>::min();
+ EA_CONSTEXPR auto MAX = eastl::numeric_limits<T>::max();
+
+ VERIFY(eastl::bit_floor(MAX) == T(1) << (DIGITS - 1));
+ VERIFY(eastl::bit_floor(MIN) == T(0));
+
+ for (int i = 4; i < eastl::numeric_limits<T>::digits; i++)
+ {
+ T power_of_two = static_cast<T>(T(1U) << i);
+ VERIFY(eastl::bit_floor(power_of_two) == power_of_two);
+ VERIFY(eastl::bit_floor(static_cast<T>(power_of_two + 1)) == power_of_two);
+ }
+ return nErrorCount;
+}
+
+template <typename T>
+static int TestBitWidth()
+{
+ int nErrorCount = 0;
+
+ VERIFY(eastl::bit_width(T(0)) == T(0));
+ VERIFY(eastl::bit_width(T(1)) == T(1));
+ VERIFY(eastl::bit_width(T(2)) == T(2));
+ VERIFY(eastl::bit_width(T(3)) == T(2));
+
+ EA_CONSTEXPR auto DIGITS = eastl::numeric_limits<T>::digits;
+ EA_CONSTEXPR auto MIN = eastl::numeric_limits<T>::min();
+ EA_CONSTEXPR auto MAX = eastl::numeric_limits<T>::max();
+
+ VERIFY(eastl::bit_width(MIN) == 0);
+ VERIFY(eastl::bit_width(MAX) == DIGITS);
+
+ for (int i = 4; i < eastl::numeric_limits<T>::digits; i++)
+ {
+ T power_of_two = static_cast<T>(T(1U) << i);
+ VERIFY(eastl::bit_width(power_of_two) == static_cast<T>(i + 1));
+ }
+
+ return nErrorCount;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// TestPowerofTwo
+//
+static int TestPowerOfTwo()
+{
+ int nErrorCount = 0;
+ nErrorCount += TestHasSingleBit<unsigned int>();
+ nErrorCount += TestHasSingleBit<unsigned char>();
+ nErrorCount += TestHasSingleBit<unsigned short>();
+ nErrorCount += TestHasSingleBit<unsigned long>();
+ nErrorCount += TestHasSingleBit<unsigned long long>();
+
+ nErrorCount += TestBitCeil<unsigned int>();
+ nErrorCount += TestBitCeil<unsigned char>();
+ nErrorCount += TestBitCeil<unsigned short>();
+ nErrorCount += TestBitCeil<unsigned long>();
+ nErrorCount += TestBitCeil<unsigned long long>();
+
+ nErrorCount += TestBitFloor<unsigned int>();
+ nErrorCount += TestBitFloor<unsigned char>();
+ nErrorCount += TestBitFloor<unsigned short>();
+ nErrorCount += TestBitFloor<unsigned long>();
+ nErrorCount += TestBitFloor<unsigned long long>();
+
+ nErrorCount += TestBitWidth<unsigned int>();
+ nErrorCount += TestBitWidth<unsigned char>();
+ nErrorCount += TestBitWidth<unsigned short>();
+ nErrorCount += TestBitWidth<unsigned long>();
+ nErrorCount += TestBitWidth<unsigned long long>();
+
+ return nErrorCount;
+}
+#endif
///////////////////////////////////////////////////////////////////////////////
// TestExtra
@@ -931,6 +1532,11 @@ int TestExtra()
nErrorCount += TestCallTraits();
nErrorCount += TestNumeric();
nErrorCount += TestAdaptors();
+#if defined(EA_COMPILER_CPP20_ENABLED)
+ nErrorCount += TestMidpoint();
+ nErrorCount += TestLerp();
+ nErrorCount += TestPowerOfTwo();
+#endif
return nErrorCount;
}
diff --git a/EASTL/test/source/TestFixedString.cpp b/EASTL/test/source/TestFixedString.cpp
index a7f7bd9..8528dc7 100644
--- a/EASTL/test/source/TestFixedString.cpp
+++ b/EASTL/test/source/TestFixedString.cpp
@@ -131,6 +131,58 @@ int TestFixedSubstring()
EATEST_VERIFY(str == "");
}
+
+ {
+ // Check that copies/moves don't become independent strings.
+ // They should all point to the same sub-string.
+ string str = "hello world";
+ fixed_substring<char> sub(str, 2, 5);
+
+ EATEST_VERIFY(sub.size() == 5);
+ EATEST_VERIFY(sub[0] == 'l');
+ EATEST_VERIFY(sub == "llo w");
+
+ vector<fixed_substring<char>> v;
+ for (eastl_size_t i = 0; i < 1000; ++i) {
+ v.push_back(sub);
+ }
+
+ sub[0] = 'g';
+ EATEST_VERIFY(str == "heglo world");
+ EATEST_VERIFY(sub == "glo w");
+
+ for (const auto& s : v){
+ EATEST_VERIFY(s == "glo w");
+ }
+
+ // copy construct
+ fixed_substring<char> sub2 = sub;
+
+ // copy assign
+ fixed_substring<char> sub3;
+ sub3 = sub;
+
+ // move construct
+ fixed_substring<char> sub4 = eastl::move(sub);
+
+ // move assign
+ fixed_substring<char> sub_again(str, 2, 5);
+ fixed_substring<char> sub5;
+ sub5 = eastl::move(sub_again);
+
+ EATEST_VERIFY(sub2 == "glo w");
+ EATEST_VERIFY(sub3 == "glo w");
+ EATEST_VERIFY(sub4 == "glo w");
+ EATEST_VERIFY(sub5 == "glo w");
+
+ str[5] = 'g';
+ EATEST_VERIFY(sub2 == "glogw");
+ EATEST_VERIFY(sub3 == "glogw");
+ EATEST_VERIFY(sub4 == "glogw");
+ EATEST_VERIFY(sub5 == "glogw");
+
+ }
+
return nErrorCount;
}
diff --git a/EASTL/test/source/TestFunctional.cpp b/EASTL/test/source/TestFunctional.cpp
index 88f4c2c..1e25200 100644
--- a/EASTL/test/source/TestFunctional.cpp
+++ b/EASTL/test/source/TestFunctional.cpp
@@ -68,14 +68,17 @@ namespace
bool operator==(const N1& n1, const N1& n1a){ return (n1.mX == n1a.mX); }
bool operator==(const N1& n1, const N2& n2) { return (n1.mX == n2.mX); }
bool operator==(const N2& n2, const N1& n1) { return (n2.mX == n1.mX); }
+ bool operator==(const volatile N1& n1, const volatile N1& n1a) { return (n1.mX == n1a.mX); }
bool operator!=(const N1& n1, const N1& n1a){ return (n1.mX != n1a.mX); }
bool operator!=(const N1& n1, const N2& n2) { return (n1.mX != n2.mX); }
bool operator!=(const N2& n2, const N1& n1) { return (n2.mX != n1.mX); }
+ bool operator!=(const volatile N1& n1, const volatile N1& n1a) { return (n1.mX != n1a.mX); }
bool operator< (const N1& n1, const N1& n1a){ return (n1.mX < n1a.mX); }
bool operator< (const N1& n1, const N2& n2) { return (n1.mX < n2.mX); }
bool operator< (const N2& n2, const N1& n1) { return (n2.mX < n1.mX); }
+ bool operator< (const volatile N1& n1, const volatile N1& n1a) { return (n1.mX < n1a.mX); }
// Used for mem_fun tests below.
@@ -260,8 +263,12 @@ int TestFunctional()
N1 n13(3);
N2 n21(1);
N2 n22(2);
- //const N1 cn11(1);
- //const N1 cn13(3);
+ const N1 cn11(1);
+ const N1 cn13(3);
+ volatile N1 vn11(1);
+ volatile N1 vn13(3);
+ const volatile N1 cvn11(1);
+ const volatile N1 cvn13(3);
equal_to_2<N1, N2> e;
EATEST_VERIFY(e(n11, n21));
@@ -269,9 +276,40 @@ int TestFunctional()
equal_to_2<N1, N1> es;
EATEST_VERIFY(es(n11, n11));
+ EATEST_VERIFY(!es(n11, n13));
- //equal_to_2<const N1, N1> ec; // To do: Make this case work.
- //EATEST_VERIFY(e(cn11, n11));
+ equal_to_2<const N1, N1> ec;
+ EATEST_VERIFY(ec(cn11, n11));
+ EATEST_VERIFY(ec(n11, cn11));
+
+ equal_to_2<N1, const N1> ec2;
+ EATEST_VERIFY(ec2(n11, cn11));
+ EATEST_VERIFY(ec2(cn11, n11));
+
+ equal_to_2<const N1, const N1> ecc;
+ EATEST_VERIFY(ecc(cn11, cn11));
+
+ equal_to_2<volatile N1, N1> ev;
+ EATEST_VERIFY(ev(vn11, n11));
+ EATEST_VERIFY(ev(n11, vn11));
+
+ equal_to_2<N1, volatile N1> ev2;
+ EATEST_VERIFY(ev2(n11, vn11));
+ EATEST_VERIFY(ev2(vn11, n11));
+
+ equal_to_2<volatile N1, volatile N1> evv;
+ EATEST_VERIFY(evv(vn11, vn11));
+
+ equal_to_2<const volatile N1, N1> ecv;
+ EATEST_VERIFY(ecv(cvn11, n11));
+ EATEST_VERIFY(ecv(n11, cvn11));
+
+ equal_to_2<N1, const volatile N1> ecv2;
+ EATEST_VERIFY(ecv2(n11, cvn11));
+ EATEST_VERIFY(ecv2(cvn11, n11));
+
+ equal_to_2<const volatile N1, const volatile N1> ecvcv;
+ EATEST_VERIFY(ecvcv(cvn11, cvn11));
// not_equal_to_2
not_equal_to_2<N1, N2> n;
@@ -280,6 +318,40 @@ int TestFunctional()
not_equal_to_2<N1, N1> ns;
EATEST_VERIFY(ns(n11, n13));
+ EATEST_VERIFY(!ns(n11, n11));
+
+ not_equal_to_2<const N1, N1> nc;
+ EATEST_VERIFY(nc(cn11, n13));
+ EATEST_VERIFY(nc(n13, cn11));
+
+ not_equal_to_2<N1, const N1> nc2;
+ EATEST_VERIFY(nc2(n13, cn11));
+ EATEST_VERIFY(nc2(cn11, n13));
+
+ not_equal_to_2<const N1, const N1> ncc;
+ EATEST_VERIFY(ncc(cn11, cn13));
+
+ not_equal_to_2<volatile N1, N1> nv;
+ EATEST_VERIFY(nv(vn11, n13));
+ EATEST_VERIFY(nv(n11, vn13));
+
+ not_equal_to_2<N1, volatile N1> nv2;
+ EATEST_VERIFY(nv2(n11, vn13));
+ EATEST_VERIFY(nv2(vn11, n13));
+
+ not_equal_to_2<volatile N1, volatile N1> nvv;
+ EATEST_VERIFY(nvv(vn11, vn13));
+
+ not_equal_to_2<const volatile N1, N1> ncv;
+ EATEST_VERIFY(ncv(cvn11, n13));
+ EATEST_VERIFY(ncv(n11, cvn13));
+
+ not_equal_to_2<N1, const volatile N1> ncv2;
+ EATEST_VERIFY(ncv2(n11, cvn13));
+ EATEST_VERIFY(ncv2(cvn11, n13));
+
+ not_equal_to_2<const volatile N1, const volatile N1> ncvcv;
+ EATEST_VERIFY(ncvcv(cvn11, cvn13));
// less_2
less_2<N1, N2> le;
@@ -288,6 +360,39 @@ int TestFunctional()
less_2<N1, N1> les;
EATEST_VERIFY(les(n11, n13));
+
+ less_2<const N1, N1> lec;
+ EATEST_VERIFY(lec(cn11, n13));
+ EATEST_VERIFY(lec(n11, cn13));
+
+ less_2<N1, const N1> lec2;
+ EATEST_VERIFY(lec2(n11, cn13));
+ EATEST_VERIFY(lec2(cn11, n13));
+
+ less_2<const N1, const N1> lecc;
+ EATEST_VERIFY(lecc(cn11, cn13));
+
+ less_2<volatile N1, N1> lev;
+ EATEST_VERIFY(lev(vn11, n13));
+ EATEST_VERIFY(lev(n11, vn13));
+
+ less_2<N1, volatile N1> lev2;
+ EATEST_VERIFY(lev2(n11, vn13));
+ EATEST_VERIFY(lev2(vn11, n13));
+
+ less_2<volatile N1, volatile N1> levv;
+ EATEST_VERIFY(levv(vn11, vn13));
+
+ less_2<const volatile N1, N1> lecv;
+ EATEST_VERIFY(lecv(cvn11, n13));
+ EATEST_VERIFY(lecv(n11, cvn13));
+
+ less_2<N1, const volatile N1> lecv2;
+ EATEST_VERIFY(lecv2(n11, cvn13));
+ EATEST_VERIFY(lecv2(cvn11, n13));
+
+ less_2<const volatile N1, const volatile N1> lecvcv;
+ EATEST_VERIFY(lecvcv(cvn11, cvn13));
}
@@ -435,6 +540,7 @@ int TestFunctional()
void Add(int addAmount) { value += addAmount; }
int GetValue() { return value; }
int& GetValueReference() { return value; }
+ void NoThrow(int inValue) EA_NOEXCEPT {}
int value;
};
@@ -444,6 +550,12 @@ int TestFunctional()
bool called = false;
};
+ struct TestFunctorNoThrow
+ {
+ void operator()() EA_NOEXCEPT { called = true; }
+ bool called = false;
+ };
+
struct TestFunctorArguments
{
void operator()(int i) { value = i; }
@@ -457,6 +569,8 @@ int TestFunctional()
static_assert(eastl::is_same<typename eastl::invoke_result<decltype(&TestStruct::Add), TestStruct, int>::type, void>::value, "incorrect type for invoke_result");
static_assert(eastl::is_invocable<decltype(&TestStruct::Add), TestStruct, int>::value, "incorrect value for is_invocable");
+ static_assert(eastl::is_nothrow_invocable<decltype(&TestStruct::NoThrow), TestStruct, int>::value, "incorrect value for is_nothrow_invocable");
+ static_assert(!eastl::is_nothrow_invocable<decltype(&TestStruct::Add), TestStruct, int>::value, "incorrect value for is_nothrow_invocable");
}
{
TestStruct a(42);
@@ -465,6 +579,8 @@ int TestFunctional()
static_assert(eastl::is_same<typename eastl::invoke_result<decltype(&TestStruct::Add), TestStruct *, int>::type, void>::value, "incorrect type for invoke_result");
static_assert(eastl::is_invocable<decltype(&TestStruct::Add), TestStruct *, int>::value, "incorrect value for is_invocable");
+ static_assert(eastl::is_nothrow_invocable<decltype(&TestStruct::NoThrow), TestStruct *, int>::value, "incorrect value for is_nothrow_invocable");
+ static_assert(!eastl::is_nothrow_invocable<decltype(&TestStruct::Add), TestStruct *, int>::value, "incorrect value for is_nothrow_invocable");
}
{
TestStruct a(42);
@@ -474,6 +590,8 @@ int TestFunctional()
static_assert(eastl::is_same<typename eastl::invoke_result<decltype(&TestStruct::Add), eastl::reference_wrapper<TestStruct>, int>::type, void>::value, "incorrect type for invoke_result");
static_assert(eastl::is_invocable<decltype(&TestStruct::Add), eastl::reference_wrapper<TestStruct>, int>::value, "incorrect value for is_invocable");
+ static_assert(eastl::is_nothrow_invocable<decltype(&TestStruct::NoThrow), eastl::reference_wrapper<TestStruct>, int>::value, "incorrect value for is_nothrow_invocable");
+ static_assert(!eastl::is_nothrow_invocable<decltype(&TestStruct::Add), eastl::reference_wrapper<TestStruct>, int>::value, "incorrect value for is_nothrow_invocable");
}
{
TestStruct a(42);
@@ -535,6 +653,16 @@ int TestFunctional()
static_assert(eastl::is_same<typename eastl::invoke_result<decltype(f)>::type, void>::value, "incorrect type for invoke_result");
static_assert(eastl::is_invocable<decltype(f)>::value, "incorrect value for is_invocable");
+ static_assert(!eastl::is_nothrow_invocable<decltype(f)>::value, "incorrect value for is_nothrow_invocable");
+ }
+ {
+ TestFunctorNoThrow f;
+ eastl::invoke(f);
+ EATEST_VERIFY(f.called);
+
+ static_assert(eastl::is_same<typename eastl::invoke_result<decltype(f)>::type, void>::value, "incorrect type for invoke_result");
+ static_assert(eastl::is_invocable<decltype(f)>::value, "incorrect value for is_invocable");
+ static_assert(eastl::is_nothrow_invocable<decltype(f)>::value, "incorrect value for is_nothrow_invocable");
}
{
TestFunctorArguments f;
@@ -545,6 +673,43 @@ int TestFunctional()
static_assert(eastl::is_invocable<decltype(f), int>::value, "incorrect value for is_invocable");
}
{
+ struct TestInvokeConstAccess
+ {
+ void ConstMemberFunc(int i) const {}
+ void ConstVolatileMemberFunc(int i) const volatile {}
+
+ int mI;
+ };
+
+ static_assert(eastl::is_invocable<decltype(&TestInvokeConstAccess::ConstMemberFunc), const TestInvokeConstAccess*, int>::value, "incorrect value for is_invocable");
+ static_assert(eastl::is_invocable<decltype(&TestInvokeConstAccess::ConstVolatileMemberFunc), const volatile TestInvokeConstAccess*, int>::value, "incorrect value for is_invocable");
+ }
+ {
+ struct TestReferenceWrapperInvoke
+ {
+ int NonConstMemberFunc(int i) { return i; }
+ int ConstMemberFunc(int i) const { return i; }
+
+ int mI = 1;
+ const int mIC = 1;
+ };
+
+ TestReferenceWrapperInvoke testStruct;
+ int ret;
+
+ ret = eastl::invoke(&TestReferenceWrapperInvoke::NonConstMemberFunc, eastl::ref(testStruct), 1);
+ EATEST_VERIFY(ret == 1);
+
+ ret = eastl::invoke(&TestReferenceWrapperInvoke::ConstMemberFunc, eastl::ref(testStruct), 1);
+ EATEST_VERIFY(ret == 1);
+
+ ret = eastl::invoke(&TestReferenceWrapperInvoke::mI, eastl::ref(testStruct));
+ EATEST_VERIFY(ret == 1);
+
+ ret = eastl::invoke(&TestReferenceWrapperInvoke::mIC, eastl::ref(testStruct));
+ EATEST_VERIFY(ret == 1);
+ }
+ {
static bool called = false;
auto f = [] {called = true;};
eastl::invoke(f);
@@ -565,16 +730,20 @@ int TestFunctional()
{
struct A {};
struct B : public A {};
+ struct C : public A {};
struct TestStruct
{
A a() { return A(); };
B b() { return B(); };
+ C c() EA_NOEXCEPT { return C(); };
};
static_assert(!eastl::is_invocable_r<B, decltype(&TestStruct::a), TestStruct>::value, "incorrect value for is_invocable_r");
static_assert(eastl::is_invocable_r<A, decltype(&TestStruct::b), TestStruct>::value, "incorrect value for is_invocable_r");
static_assert(eastl::is_invocable_r<B, decltype(&TestStruct::b), TestStruct>::value, "incorrect value for is_invocable_r");
+ static_assert(!eastl::is_nothrow_invocable_r<B, decltype(&TestStruct::b), TestStruct>::value, "incorrect value for is_nothrow_invocable_r");
+ static_assert(eastl::is_nothrow_invocable_r<C, decltype(&TestStruct::c), TestStruct>::value, "incorrect value for is_nothrow_invocable_r");
}
}
@@ -1322,5 +1491,39 @@ struct TestInvokeResult
};
template struct eastl::invoke_result<decltype(&TestInvokeResult::f), TestInvokeResult, void>;
+
static_assert(!eastl::is_invocable<decltype(&TestInvokeResult::f), TestInvokeResult, void>::value, "incorrect value for is_invocable");
+static_assert(!eastl::is_invocable<decltype(&TestInvokeResult::f), TestInvokeResult, int, int>::value, "incorrect value for is_invocable");
static_assert(eastl::is_invocable<decltype(&TestInvokeResult::f), TestInvokeResult, int>::value, "incorrect value for is_invocable");
+
+static_assert(!eastl::is_invocable_r<int, decltype(&TestInvokeResult::f), TestInvokeResult, void>::value, "incorrect value for is_invocable_r");
+static_assert(!eastl::is_invocable_r<void, decltype(&TestInvokeResult::f), TestInvokeResult, int, int>::value, "incorrect value for is_invocable_r");
+static_assert(eastl::is_invocable_r<void, decltype(&TestInvokeResult::f), TestInvokeResult, int>::value, "incorrect value for is_invocable_r");
+static_assert(eastl::is_invocable_r<int, decltype(&TestInvokeResult::f), TestInvokeResult, int>::value, "incorrect value for is_invocable_r");
+
+struct TestCallableInvokeResult
+{
+ int operator()(int i) {return i;}
+};
+
+template struct eastl::invoke_result<TestCallableInvokeResult, void>;
+
+static_assert(!eastl::is_invocable<TestCallableInvokeResult, void>::value, "incorrect value for is_invocable");
+static_assert(!eastl::is_invocable<TestCallableInvokeResult, int, int>::value, "incorrect value for is_invocable");
+static_assert(eastl::is_invocable<TestCallableInvokeResult, int>::value, "incorrect value for is_invocable");
+
+static_assert(!eastl::is_invocable_r<int, TestCallableInvokeResult, void>::value, "incorrect value for is_invocable_r");
+static_assert(!eastl::is_invocable_r<void, TestCallableInvokeResult, int, int>::value, "incorrect value for is_invocable_r");
+static_assert(eastl::is_invocable_r<void, TestCallableInvokeResult, int>::value, "incorrect value for is_invocable_r");
+static_assert(eastl::is_invocable_r<int, TestCallableInvokeResult, int>::value, "incorrect value for is_invocable_r");
+
+typedef decltype(eastl::ref(eastl::declval<TestCallableInvokeResult&>())) TestCallableRefInvokeResult;
+
+static_assert(!eastl::is_invocable<TestCallableRefInvokeResult, void>::value, "incorrect value for is_invocable");
+static_assert(!eastl::is_invocable<TestCallableRefInvokeResult, int, int>::value, "incorrect value for is_invocable");
+static_assert(eastl::is_invocable<TestCallableRefInvokeResult, int>::value, "incorrect value for is_invocable");
+
+static_assert(!eastl::is_invocable_r<int, TestCallableRefInvokeResult, void>::value, "incorrect value for is_invocable_r");
+static_assert(!eastl::is_invocable_r<void, TestCallableRefInvokeResult, int, int>::value, "incorrect value for is_invocable_r");
+static_assert(eastl::is_invocable_r<void, TestCallableRefInvokeResult, int>::value, "incorrect value for is_invocable_r");
+static_assert(eastl::is_invocable_r<int, TestCallableRefInvokeResult, int>::value, "incorrect value for is_invocable_r");
diff --git a/EASTL/test/source/TestHash.cpp b/EASTL/test/source/TestHash.cpp
index eff6156..1bcf996 100644
--- a/EASTL/test/source/TestHash.cpp
+++ b/EASTL/test/source/TestHash.cpp
@@ -746,14 +746,16 @@ int TestHash()
{ // hash_set erase_if
hash_set<int> m = {0, 1, 2, 3, 4};
- eastl::erase_if(m, [](auto i) { return i % 2 == 0; });
+ auto numErased = eastl::erase_if(m, [](auto i) { return i % 2 == 0; });
VERIFY((m == hash_set<int>{1, 3}));
+ VERIFY(numErased == 3);
}
{ // hash_multiset erase_if
hash_multiset<int> 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; });
+ auto numErased = eastl::erase_if(m, [](auto i) { return i % 2 == 0; });
VERIFY((m == hash_multiset<int>{1, 1, 1, 3}));
+ VERIFY(numErased == 12);
}
@@ -943,15 +945,17 @@ int TestHash()
{ // hash_map erase_if
hash_map<int, int> m = {{0, 0}, {1, 1}, {2, 2}, {3, 3}, {4, 4}};
- eastl::erase_if(m, [](auto p) { return p.first % 2 == 0; });
+ auto numErased = eastl::erase_if(m, [](auto p) { return p.first % 2 == 0; });
VERIFY((m == hash_map<int, int>{{1, 1}, {3, 3}}));
+ VERIFY(numErased == 3);
}
{ // hash_multimap erase_if
hash_multimap<int, int> 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; });
+ auto numErased = eastl::erase_if(m, [](auto p) { return p.first % 2 == 0; });
VERIFY((m == hash_multimap<int, int>{{1, 1}, {3, 3}, {3, 3}}));
+ VERIFY(numErased == 9);
}
@@ -994,9 +998,19 @@ int TestHash()
EATEST_VERIFY(it != hashSet.end());
else
EATEST_VERIFY(it == hashSet.end());
+
+ string::CtorSprintf cs;
+ string s(cs, "%d", i);
+
+ it = hashSet.find_as(s);
+ if (i < kCount)
+ EATEST_VERIFY(it != hashSet.end());
+ else
+ EATEST_VERIFY(it == hashSet.end());
}
}
+
{
// Test const containers.
const hash_set<int> constHashSet;
diff --git a/EASTL/test/source/TestIntrusiveHash.cpp b/EASTL/test/source/TestIntrusiveHash.cpp
index 4fd8215..f089aab 100644
--- a/EASTL/test/source/TestIntrusiveHash.cpp
+++ b/EASTL/test/source/TestIntrusiveHash.cpp
@@ -617,6 +617,12 @@ int TestIntrusiveHash()
itfc = ihmMW1Const.find_as(7.f);
VERIFY(itfc->mKey == 7);
+
+ itf = ihmMW1.find_as(8);
+ VERIFY(itf->mKey == 8);
+
+ itfc = ihmMW1Const.find_as(8);
+ VERIFY(itfc->mKey == 8);
// iterator find_as(const U& u, UHash uhash, BinaryPredicate predicate);
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;
diff --git a/EASTL/test/source/TestList.cpp b/EASTL/test/source/TestList.cpp
index 8a5e057..001b79a 100644
--- a/EASTL/test/source/TestList.cpp
+++ b/EASTL/test/source/TestList.cpp
@@ -975,20 +975,115 @@ int TestList()
{
eastl::list<int> l = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- eastl::erase(l, 3);
- eastl::erase(l, 5);
- eastl::erase(l, 7);
+ auto numErased = eastl::erase(l, 3);
+ VERIFY(numErased == 1);
+ numErased = eastl::erase(l, 5);
+ VERIFY(numErased == 1);
+ numErased = eastl::erase(l, 7);
+ VERIFY(numErased == 1);
VERIFY((l == eastl::list<int>{1, 2, 4, 6, 8, 9}));
}
{
eastl::list<int> l = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- eastl::erase_if(l, [](auto i) { return i % 2 == 0; });
+ auto numErased = eastl::erase_if(l, [](auto i) { return i % 2 == 0; });
VERIFY((l == eastl::list<int>{1, 3, 5, 7, 9}));
+ VERIFY(numErased == 4);
}
}
+ { // Test global operators
+ {
+ eastl::list<int> list1 = {0, 1, 2, 3, 4, 5};
+ eastl::list<int> list2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ eastl::list<int> list3 = {5, 6, 7, 8};
+
+ VERIFY(list1 == list1);
+ VERIFY(!(list1 != list1));
+
+ VERIFY(list1 != list2);
+ VERIFY(list2 != list3);
+ VERIFY(list1 != list3);
+
+ VERIFY(list1 < list2);
+ VERIFY(list1 <= list2);
+
+ VERIFY(list2 > list1);
+ VERIFY(list2 >= list1);
+
+ VERIFY(list3 > list1);
+ VERIFY(list3 > list2);
+ }
+
+ // three way comparison operator
+#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+ {
+ eastl::list<int> list1 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ eastl::list<int> list2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+
+ // Verify equality between list1 and list2
+ VERIFY((list1 <=> list2) == 0);
+ VERIFY(!((list1 <=> list2) != 0));
+ VERIFY((list1 <=> list2) <= 0);
+ VERIFY((list1 <=> list2) >= 0);
+ VERIFY(!((list1 <=> list2) < 0));
+ VERIFY(!((list1 <=> list2) > 0));
+
+ list1.push_back(100); // Make list1 less than list2.
+ list2.push_back(101);
+
+ // Verify list1 < list2
+ VERIFY(!((list1 <=> list2) == 0));
+ VERIFY((list1 <=> list2) != 0);
+ VERIFY((list1 <=> list2) <= 0);
+ VERIFY(!((list1 <=> list2) >= 0));
+ VERIFY(((list1 <=> list2) < 0));
+ VERIFY(!((list1 <=> list2) > 0));
+
+ for (int i = 0; i < 3; i++) // Make the length of list2 less than list1
+ list2.pop_back();
+
+ // Verify list2.size() < list1.size() and list2 is a subset of list1
+ VERIFY(!((list1 <=> list2) == 0));
+ VERIFY((list1 <=> list2) != 0);
+ VERIFY((list1 <=> list2) >= 0);
+ VERIFY(!((list1 <=> list2) <= 0));
+ VERIFY(((list1 <=> list2) > 0));
+ VERIFY(!((list1 <=> list2) < 0));
+ }
+
+ {
+ eastl::list<int> list1 = {1, 2, 3, 4, 5, 6, 7};
+ eastl::list<int> list2 = {7, 6, 5, 4, 3, 2, 1};
+ eastl::list<int> list3 = {1, 2, 3, 4};
+
+ struct weak_ordering_list
+ {
+ eastl::list<int> list;
+ inline std::weak_ordering operator<=>(const weak_ordering_list& b) const { return list <=> b.list; }
+ };
+
+ VERIFY(synth_three_way{}(weak_ordering_list{list1}, weak_ordering_list{list2}) == std::weak_ordering::less);
+ VERIFY(synth_three_way{}(weak_ordering_list{list3}, weak_ordering_list{list1}) == std::weak_ordering::less);
+ VERIFY(synth_three_way{}(weak_ordering_list{list2}, weak_ordering_list{list1}) == std::weak_ordering::greater);
+ VERIFY(synth_three_way{}(weak_ordering_list{list2}, weak_ordering_list{list3}) == std::weak_ordering::greater);
+ VERIFY(synth_three_way{}(weak_ordering_list{list1}, weak_ordering_list{list1}) == std::weak_ordering::equivalent);
+
+ struct strong_ordering_list
+ {
+ eastl::list<int> list;
+ inline std::strong_ordering operator<=>(const strong_ordering_list& b) const { return list <=> b.list; }
+ };
+
+ VERIFY(synth_three_way{}(strong_ordering_list{list1}, strong_ordering_list{list2}) == std::strong_ordering::less);
+ VERIFY(synth_three_way{}(strong_ordering_list{list3}, strong_ordering_list{list1}) == std::strong_ordering::less);
+ VERIFY(synth_three_way{}(strong_ordering_list{list2}, strong_ordering_list{list1}) == std::strong_ordering::greater);
+ VERIFY(synth_three_way{}(strong_ordering_list{list2}, strong_ordering_list{list3}) == std::strong_ordering::greater);
+ VERIFY(synth_three_way{}(strong_ordering_list{list1}, strong_ordering_list{list1}) == std::strong_ordering::equal);
+ }
+#endif
+ }
return nErrorCount;
}
diff --git a/EASTL/test/source/TestMap.cpp b/EASTL/test/source/TestMap.cpp
index df4a195..0df8c88 100644
--- a/EASTL/test/source/TestMap.cpp
+++ b/EASTL/test/source/TestMap.cpp
@@ -120,6 +120,19 @@ int TestMap()
}
{
+ eastl::map<int*, int> m;
+ int* ip = (int*)(uintptr_t)0xDEADC0DE;
+
+ m[ip] = 0;
+
+ auto it = m.find_as(ip, eastl::less_2<int*, int*>{});
+ EATEST_VERIFY(it != m.end());
+
+ it = m.find_as((int*)(uintptr_t)0xDEADC0DE, eastl::less_2<int*, int*>{});
+ EATEST_VERIFY(it != m.end());
+ }
+
+ {
// User reports that vector<map<enum,enum>> is crashing after the recent changes to add rvalue move and emplace support to rbtree.
typedef eastl::map<int, int> IntIntMap;
typedef eastl::vector<IntIntMap> IntIntMapArray;
@@ -134,15 +147,23 @@ int TestMap()
{
typedef eastl::map<int, int> IntIntMap;
IntIntMap map1;
+ map1[1] = 1;
+ map1[3] = 3;
#if EASTL_EXCEPTIONS_ENABLED
EATEST_VERIFY_THROW(map1.at(0));
+ EATEST_VERIFY_THROW(map1.at(2));
+ EATEST_VERIFY_THROW(map1.at(4));
#endif
- map1[0]=1;
+ map1[0] = 1;
#if EASTL_EXCEPTIONS_ENABLED
EATEST_VERIFY_NOTHROW(map1.at(0));
+ EATEST_VERIFY_NOTHROW(map1.at(1));
+ EATEST_VERIFY_NOTHROW(map1.at(3));
#endif
EATEST_VERIFY(map1.at(0) == 1);
+ EATEST_VERIFY(map1.at(1) == 1);
+ EATEST_VERIFY(map1.at(3) == 3);
const IntIntMap map2;
const IntIntMap map3(map1);
@@ -210,16 +231,65 @@ int TestMap()
{ // Test erase_if
eastl::map<int, int> m = {{0, 0}, {1, 1}, {2, 2}, {3, 3}, {4, 4}};
- eastl::erase_if(m, [](auto p) { return p.first % 2 == 0; });
+ auto numErased = eastl::erase_if(m, [](auto p) { return p.first % 2 == 0; });
VERIFY((m == eastl::map<int, int>{{1, 1},{3, 3}}));
+ VERIFY(numErased == 3);
}
{ // Test erase_if
eastl::multimap<int, int> 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<int, int>{{1, 1}, {1, 1}, {3, 3}}));
+ auto numErased = eastl::erase_if(m, [](auto p) { return p.first % 2 == 0; });
+ VERIFY((m == eastl::multimap<int, int>{{1, 1}, {1, 1}, {3, 3}}));;
+ VERIFY(numErased == 7);
}
+#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+ { // Test map <=>
+ eastl::map<int, int> m1 = {{0, 0}, {1, 1}, {2, 2}, {3, 3}, {4, 4}};
+ eastl::map<int, int> m2 = {{4, 4}, {3, 3}, {2, 2}, {1, 1}, {0, 0}};
+ eastl::map<int, int> m3 = {{0, 1}, {2, 3}, {4, 5}, {6, 7}, {8, 9}};
+ eastl::map<int, int> m4 = {{1, 0}, {3, 2}, {5, 4}, {7, 6}, {9, 8}};
+ eastl::map<int, int> m5 = {{0, 1}, {2, 3}, {4, 5}};
+
+ VERIFY(m1 == m2);
+ VERIFY(m1 != m3);
+ VERIFY(m3 != m4);
+ VERIFY(m3 < m4);
+ VERIFY(m5 < m4);
+ VERIFY(m5 < m3);
+
+
+ VERIFY((m1 <=> m2) == 0);
+ VERIFY((m1 <=> m3) != 0);
+ VERIFY((m3 <=> m4) != 0);
+ VERIFY((m3 <=> m4) < 0);
+ VERIFY((m5 <=> m4) < 0);
+ VERIFY((m5 <=> m3) < 0);
+ }
+
+ { // Test multimap <=>
+ eastl::multimap<int, int> m1 = {{0, 0}, {0, 0}, {1, 1}, {1, 1}, {2, 2}, {2, 2}, {3, 3}, {3, 3}, {4, 4}, {4, 4}};
+ eastl::multimap<int, int> m2 = {{0, 0}, {1, 1}, {2, 2}, {3, 3}, {4, 4}, {4, 4}, {3, 3}, {2, 2}, {1, 1}, {0, 0}};
+ eastl::multimap<int, int> m3 = {{0, 1}, {2, 3}, {4, 5}, {0, 1}, {2, 3}, {4, 5}, {6, 7}, {8, 9}};
+ eastl::multimap<int, int> m4 = {{1, 0}, {3, 2}, {5, 4}, {1, 0}, {3, 2}, {5, 4}, {7, 6}, {9, 8}};
+ eastl::multimap<int, int> m5 = {{10, 11}, {10, 11}};
+
+ VERIFY(m1 == m2);
+ VERIFY(m1 != m3);
+ VERIFY(m3 != m4);
+ VERIFY(m3 < m4);
+ VERIFY(m5 > m4);
+ VERIFY(m5 > m3);
+
+ VERIFY((m1 <=> m2) == 0);
+ VERIFY((m1 <=> m3) != 0);
+ VERIFY((m3 <=> m4) != 0);
+ VERIFY((m3 <=> m4) < 0);
+ VERIFY((m5 <=> m4) > 0);
+ VERIFY((m5 <=> m3) > 0);
+ }
+#endif
+
return nErrorCount;
}
diff --git a/EASTL/test/source/TestMap.h b/EASTL/test/source/TestMap.h
index 09353cd..8d480cf 100644
--- a/EASTL/test/source/TestMap.h
+++ b/EASTL/test/source/TestMap.h
@@ -1248,11 +1248,18 @@ int TestMapCpp17()
VERIFY(toMap.size() == 1);
}
+ auto ctorCount = TestObject::sTOCtorCount;
+
{ // verify duplicate not inserted
auto result = toMap.try_emplace(7, mapped_type(7)); // test fwding to copy-ctor
VERIFY(!result.second);
VERIFY(result.first->second == mapped_type(7));
VERIFY(toMap.size() == 1);
+
+ // we explicitly constructed an element for the parameter
+ // and one for the VERIFY check
+ ctorCount += 2;
+ VERIFY(ctorCount == TestObject::sTOCtorCount);
}
{ // verify duplicate not inserted
@@ -1261,6 +1268,9 @@ int TestMapCpp17()
VERIFY(result->first == 7);
VERIFY(result->second == mapped_type(7));
VERIFY(toMap.size() == 1);
+ // we explicitly constructed an element for the VERIFY check
+ ++ctorCount;
+ VERIFY(ctorCount == TestObject::sTOCtorCount);
}
{ // verify duplicate not inserted
@@ -1269,20 +1279,36 @@ int TestMapCpp17()
VERIFY(result->first == 7);
VERIFY(result->second == mapped_type(7));
VERIFY(toMap.size() == 1);
+
+ // we explicitly constructed an element for the parameter
+ // and one for the VERIFY check
+ ctorCount += 2;
+ VERIFY(ctorCount == TestObject::sTOCtorCount);
}
{
{
- auto result = toMap.try_emplace(8, 8);
+ auto result = toMap.try_emplace(8, 8);
+ // emplacing a new value should call exactly one constructor,
+ // when the value is constructed in place inside the container.
+ ++ctorCount;
VERIFY(result.second);
VERIFY(result.first->second == mapped_type(8));
+ // One more constructor for the temporary in the VERIFY
+ ++ctorCount;
VERIFY(toMap.size() == 2);
+ VERIFY(ctorCount == TestObject::sTOCtorCount);
}
{
- auto result = toMap.try_emplace(9, mapped_type(9));
+ auto result = toMap.try_emplace(9, mapped_type(9));
VERIFY(result.second);
VERIFY(result.first->second == mapped_type(9));
VERIFY(toMap.size() == 3);
+ // one more constructor for the temporary argument,
+ // one for moving it to the container, and one for the VERIFY
+ ctorCount += 3;
+ VERIFY(ctorCount == TestObject::sTOCtorCount);
+
}
}
}
diff --git a/EASTL/test/source/TestMemory.cpp b/EASTL/test/source/TestMemory.cpp
index 4e25738..77caf9f 100644
--- a/EASTL/test/source/TestMemory.cpp
+++ b/EASTL/test/source/TestMemory.cpp
@@ -133,6 +133,23 @@ eastl::late_constructed<LCTestObject, false, true> gLCTestObjectFalseTrue;
eastl::late_constructed<LCTestObject, false, false> gLCTestObjectFalseFalse;
eastl::late_constructed<LCTestObject, true, false> gLCTestObjectTrueFalse;
+struct TypeWithPointerTraits {};
+
+namespace eastl
+{
+ template <>
+ struct pointer_traits<TypeWithPointerTraits>
+ {
+ // Note: only parts of the traits we are interested to test are defined here.
+ static const int* to_address(TypeWithPointerTraits)
+ {
+ return &a;
+ }
+
+ inline static constexpr int a = 42;
+ };
+}
+
///////////////////////////////////////////////////////////////////////////////
// TestMemory
@@ -684,6 +701,33 @@ int TestMemory()
}
}
+ // to_address
+ {
+ // Normal pointers.
+ int a;
+ int* ptrA = &a;
+ EATEST_VERIFY(ptrA == to_address(ptrA));
+
+ // Smart pointer.
+ struct MockSmartPointer
+ {
+ const int* operator->() const
+ {
+ return &a;
+ }
+
+ int a = 42;
+ };
+
+ MockSmartPointer sp;
+ EATEST_VERIFY(&sp.a == to_address(sp));
+
+ // Type with specialized pointer_traits.
+ TypeWithPointerTraits t;
+ const int* result = to_address(t);
+ EATEST_VERIFY(result != nullptr && *result == 42);
+ }
+
{
// Test that align handles integral overflow correctly and returns NULL.
void* ptr;
diff --git a/EASTL/test/source/TestNumericLimits.cpp b/EASTL/test/source/TestNumericLimits.cpp
index 440715b..1964442 100644
--- a/EASTL/test/source/TestNumericLimits.cpp
+++ b/EASTL/test/source/TestNumericLimits.cpp
@@ -64,6 +64,11 @@ int TestNumericLimits()
EATEST_VERIFY(eastl::numeric_limits<wchar_t>::is_bounded);
EATEST_VERIFY(eastl::numeric_limits<wchar_t>::max() != 0);
+ #if defined(EA_CHAR8_UNIQUE) && EA_CHAR8_UNIQUE
+ EATEST_VERIFY(eastl::numeric_limits<char8_t>::is_bounded);
+ EATEST_VERIFY(eastl::numeric_limits<char8_t>::max() != 0);
+ #endif
+
EATEST_VERIFY(eastl::numeric_limits<char16_t>::is_bounded);
EATEST_VERIFY(eastl::numeric_limits<char16_t>::max() != 0);
diff --git a/EASTL/test/source/TestOptional.cpp b/EASTL/test/source/TestOptional.cpp
index 6c1fa4f..36307ad 100644
--- a/EASTL/test/source/TestOptional.cpp
+++ b/EASTL/test/source/TestOptional.cpp
@@ -18,12 +18,17 @@ struct IntStruct
int data;
};
+#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+auto operator<=>(const IntStruct& lhs, const IntStruct& rhs) { return lhs.data <=> rhs.data; }
+#else
bool operator<(const IntStruct& lhs, const IntStruct& rhs)
{ return lhs.data < rhs.data; }
+#endif
bool operator==(const IntStruct& lhs, const IntStruct& rhs)
{ return lhs.data == rhs.data; }
+
/////////////////////////////////////////////////////////////////////////////
struct destructor_test
{
@@ -476,6 +481,43 @@ int TestOptional()
VERIFY(o >= nullopt);
}
+ #if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+ {
+ optional<IntStruct> o(in_place, 10);
+ optional<IntStruct> e;
+
+ VERIFY((o <=> IntStruct(42)) < 0);
+ VERIFY((o <=> IntStruct(2)) >= 0);
+ VERIFY((o <=> IntStruct(10)) >= 0);
+ VERIFY((e <=> o) < 0);
+ VERIFY((e <=> IntStruct(10)) < 0);
+
+ VERIFY((o <=> IntStruct(4)) > 0);
+ VERIFY(o <=> IntStruct(42) <= 0);
+
+ VERIFY((o <=> IntStruct(4)) >= 0);
+ VERIFY((o <=> IntStruct(10)) >= 0);
+ VERIFY((IntStruct(4) <=> o) <= 0);
+ VERIFY((IntStruct(10) <=> o) <= 0);
+
+ VERIFY((o <=> IntStruct(10)) == 0);
+ VERIFY((o->data <=> IntStruct(10).data) == 0);
+
+ VERIFY((o <=> IntStruct(11)) != 0);
+ VERIFY((o->data <=> IntStruct(11).data) != 0);
+
+ VERIFY((e <=> nullopt) == 0);
+ VERIFY((nullopt <=> e) == 0);
+
+ VERIFY((o <=> nullopt) != 0);
+ VERIFY((nullopt <=> o) != 0);
+ VERIFY((nullopt <=> o) < 0);
+ VERIFY((o <=> nullopt) > 0);
+ VERIFY((nullopt <=> o) <= 0);
+ VERIFY((o <=> nullopt) >= 0);
+ }
+ #endif
+
// hash
{
{
@@ -536,13 +578,13 @@ int TestOptional()
// optional rvalue tests
{
- VERIFY(*optional<int>(1) == 1);
- VERIFY( optional<int>(1).value() == 1);
- VERIFY( optional<int>(1).value_or(0xdeadf00d) == 1);
- VERIFY( optional<int>().value_or(0xdeadf00d) == 0xdeadf00d);
- VERIFY( optional<int>(1).has_value() == true);
- VERIFY( optional<int>().has_value() == false);
- VERIFY( optional<IntStruct>(in_place, 10)->data == 10);
+ VERIFY(*optional<uint32_t>(1u) == 1u);
+ VERIFY(optional<uint32_t>(1u).value() == 1u);
+ VERIFY(optional<uint32_t>(1u).value_or(0xdeadf00d) == 1u);
+ VERIFY(optional<uint32_t>().value_or(0xdeadf00d) == 0xdeadf00d);
+ VERIFY(optional<uint32_t>(1u).has_value() == true);
+ VERIFY(optional<uint32_t>().has_value() == false);
+ VERIFY( optional<IntStruct>(in_place, 10)->data == 10);
}
@@ -611,7 +653,7 @@ int TestOptional()
copyCtorCalledWithUninitializedValue = moveCtorCalledWithUninitializedValue = false;
struct local
{
- int val;
+ uint32_t val;
local()
: val(0xabcdabcd)
{}
diff --git a/EASTL/test/source/TestSList.cpp b/EASTL/test/source/TestSList.cpp
index d73f2bc..94a4d3a 100644
--- a/EASTL/test/source/TestSList.cpp
+++ b/EASTL/test/source/TestSList.cpp
@@ -795,36 +795,134 @@ int TestSList()
{
slist<int> l = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
- eastl::erase(l, 5);
+ auto numErased = eastl::erase(l, 5);
VERIFY((l == slist<int>{0, 1, 2, 3, 4, 6, 7, 8, 9}));
+ VERIFY(numErased == 1);
- eastl::erase(l, 7);
+ numErased = eastl::erase(l, 7);
VERIFY((l == slist<int>{0, 1, 2, 3, 4, 6, 8, 9}));
+ VERIFY(numErased == 1);
- eastl::erase(l, 2);
+ numErased = eastl::erase(l, 2);
VERIFY((l == slist<int>{0, 1, 3, 4, 6, 8, 9}));
+ VERIFY(numErased == 1);
- eastl::erase(l, 0);
+ numErased = eastl::erase(l, 0);
VERIFY((l == slist<int>{1, 3, 4, 6, 8, 9}));
+ VERIFY(numErased == 1);
- eastl::erase(l, 4);
+ numErased = eastl::erase(l, 4);
VERIFY((l == slist<int>{1, 3, 6, 8, 9}));
+ VERIFY(numErased == 1);
}
{
slist<int> l = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
- eastl::erase_if(l, [](auto e) { return e % 2 == 0; });
+ auto numErased = eastl::erase_if(l, [](auto e) { return e % 2 == 0; });
VERIFY((l == slist<int>{1, 3, 5, 7, 9}));
+ VERIFY(numErased == 5);
- eastl::erase_if(l, [](auto e) { return e == 5; });
+ numErased = eastl::erase_if(l, [](auto e) { return e == 5; });
VERIFY((l == slist<int>{1, 3, 7, 9}));
+ VERIFY(numErased == 1);
- eastl::erase_if(l, [](auto e) { return e % 3 == 0; });
+ numErased = eastl::erase_if(l, [](auto e) { return e % 3 == 0; });
VERIFY((l == slist<int>{1, 7}));
+ VERIFY(numErased == 2);
}
}
+ { // Test global operators
+ {
+ slist<int> list1 = {0, 1, 2, 3, 4, 5};
+ slist<int> list2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ slist<int> list3 = {5, 6, 7, 8};
+
+ VERIFY(list1 == list1);
+ VERIFY(!(list1 != list1));
+
+ VERIFY(list1 != list2);
+ VERIFY(list2 != list3);
+ VERIFY(list1 != list3);
+
+ VERIFY(list1 < list2);
+ VERIFY(list1 <= list2);
+
+ VERIFY(list2 > list1);
+ VERIFY(list2 >= list1);
+
+ VERIFY(list3 > list1);
+ VERIFY(list3 > list2);
+ }
+
+#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+ {
+ slist<int> list1 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ slist<int> list2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ slist<int> list3 = {-1, 0, 1, 2, 3, 4, 5};
+
+ // Verify equality between list1 and list2
+ VERIFY((list1 <=> list2) == 0);
+ VERIFY(!((list1 <=> list2) != 0));
+ VERIFY((list1 <=> list2) <= 0);
+ VERIFY((list1 <=> list2) >= 0);
+ VERIFY(!((list1 <=> list2) < 0));
+ VERIFY(!((list1 <=> list2) > 0));
+
+ list1.push_front(-2); // Make list1 less than list2.
+ list2.push_front(-1);
+
+ // Verify list1 < list2
+ VERIFY(!((list1 <=> list2) == 0));
+ VERIFY((list1 <=> list2) != 0);
+ VERIFY((list1 <=> list2) <= 0);
+ VERIFY(!((list1 <=> list2) >= 0));
+ VERIFY(((list1 <=> list2) < 0));
+ VERIFY(!((list1 <=> list2) > 0));
+
+
+ // Verify list3.size() < list2.size() and list3 is a subset of list2
+ VERIFY(!((list3 <=> list2) == 0));
+ VERIFY((list3 <=> list2) != 0);
+ VERIFY((list3 <=> list2) <= 0);
+ VERIFY(!((list3 <=> list2) >= 0));
+ VERIFY(((list3 <=> list2) < 0));
+ VERIFY(!((list3 <=> list2) > 0));
+ }
+
+ {
+ slist<int> list1 = {1, 2, 3, 4, 5, 6, 7};
+ slist<int> list2 = {7, 6, 5, 4, 3, 2, 1};
+ slist<int> list3 = {1, 2, 3, 4};
+
+ struct weak_ordering_slist
+ {
+ slist<int> slist;
+ inline std::weak_ordering operator<=>(const weak_ordering_slist& b) const { return slist <=> b.slist; }
+ };
+
+ VERIFY(synth_three_way{}(weak_ordering_slist{list1}, weak_ordering_slist{list2}) == std::weak_ordering::less);
+ VERIFY(synth_three_way{}(weak_ordering_slist{list3}, weak_ordering_slist{list1}) == std::weak_ordering::less);
+ VERIFY(synth_three_way{}(weak_ordering_slist{list2}, weak_ordering_slist{list1}) == std::weak_ordering::greater);
+ VERIFY(synth_three_way{}(weak_ordering_slist{list2}, weak_ordering_slist{list3}) == std::weak_ordering::greater);
+ VERIFY(synth_three_way{}(weak_ordering_slist{list1}, weak_ordering_slist{list1}) == std::weak_ordering::equivalent);
+
+ struct strong_ordering_slist
+ {
+ slist<int> slist;
+ inline std::strong_ordering operator<=>(const strong_ordering_slist& b) const { return slist <=> b.slist; }
+ };
+
+ VERIFY(synth_three_way{}(strong_ordering_slist{list1}, strong_ordering_slist{list2}) == std::strong_ordering::less);
+ VERIFY(synth_three_way{}(strong_ordering_slist{list3}, strong_ordering_slist{list1}) == std::strong_ordering::less);
+ VERIFY(synth_three_way{}(strong_ordering_slist{list2}, strong_ordering_slist{list1}) == std::strong_ordering::greater);
+ VERIFY(synth_three_way{}(strong_ordering_slist{list2}, strong_ordering_slist{list3}) == std::strong_ordering::greater);
+ VERIFY(synth_three_way{}(strong_ordering_slist{list1}, strong_ordering_slist{list1}) == std::strong_ordering::equal);
+ }
+#endif
+ }
+
return nErrorCount;
}
diff --git a/EASTL/test/source/TestSet.cpp b/EASTL/test/source/TestSet.cpp
index 1adc12f..9a590c2 100644
--- a/EASTL/test/source/TestSet.cpp
+++ b/EASTL/test/source/TestSet.cpp
@@ -162,16 +162,60 @@ int TestSet()
{ // set erase_if tests
set<int> s = {0, 1, 2, 3, 4};
- eastl::erase_if(s, [](auto i) { return i % 2 == 0;});
+ auto numErased = eastl::erase_if(s, [](auto i) { return i % 2 == 0;});
VERIFY((s == set<int>{1,3}));
+ VERIFY(numErased == 3);
}
{ // multiset erase_if tests
multiset<int> s = {0, 0, 0, 0, 0, 1, 1, 1, 2, 3, 3, 3, 4};
- eastl::erase_if(s, [](auto i) { return i % 2 == 0;});
+ auto numErased = eastl::erase_if(s, [](auto i) { return i % 2 == 0;});
VERIFY((s == multiset<int>{1, 1, 1, 3, 3, 3}));
+ VERIFY(numErased == 7);
}
+#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+ { // Test set <=>
+ set<int> s1 = {0, 1, 2, 3, 4};
+ set<int> s2 = {4, 3, 2, 1, 0};
+ set<int> s3 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ set<int> s4 = {1, 2, 3, 4, 5, 6};
+ set<int> s5 = {9};
+
+ VERIFY(s1 == s2);
+ VERIFY(s1 != s3);
+ VERIFY(s3 > s4);
+ VERIFY(s5 > s4);
+ VERIFY(s5 > s3);
+
+ VERIFY((s1 <=> s2) == 0);
+ VERIFY((s1 <=> s3) != 0);
+ VERIFY((s3 <=> s4) > 0);
+ VERIFY((s5 <=> s4) > 0);
+ VERIFY((s5 <=> s3) > 0);
+ }
+
+ { // Test multiset <=>
+ multiset<int> s1 = {0, 0, 0, 1, 1, 2, 3, 3, 4};
+ multiset<int> s2 = {4, 3, 3, 2, 1, 1, 0, 0, 0};
+ multiset<int> s3 = {1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9};
+ multiset<int> s4 = {1, 1, 2, 2, 3, 4, 5, 5, 6};
+ multiset<int> s5 = {9};
+
+ VERIFY(s1 == s2);
+ VERIFY(s1 != s3);
+ VERIFY(s3 > s4);
+ VERIFY(s5 > s4);
+ VERIFY(s5 > s3);
+
+ VERIFY((s1 <=> s2) == 0);
+ VERIFY((s1 <=> s3) != 0);
+ VERIFY((s3 <=> s4) > 0);
+ VERIFY((s5 <=> s4) > 0);
+ VERIFY((s5 <=> s3) > 0);
+ }
+#endif
+
{
// user reported regression: ensure container elements are NOT
// moved from during the eastl::set construction process.
diff --git a/EASTL/test/source/TestSmartPtr.cpp b/EASTL/test/source/TestSmartPtr.cpp
index dc94b96..8052392 100644
--- a/EASTL/test/source/TestSmartPtr.cpp
+++ b/EASTL/test/source/TestSmartPtr.cpp
@@ -8,6 +8,7 @@
#include "GetTypeName.h"
#include <EAStdC/EAString.h>
#include <EAStdC/EAStopwatch.h>
+#include <EASTL/atomic.h>
#include <EASTL/core_allocator_adapter.h>
#include <EASTL/core_allocator.h>
#include <EASTL/intrusive_ptr.h>
@@ -800,6 +801,38 @@ static int Test_unique_ptr()
}
#endif
+ #if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+ {
+ unique_ptr<int> pT1(new int(5));
+ unique_ptr<int> pT2(new int(10));
+ unique_ptr<int> pT3(new int(0));
+
+ EATEST_VERIFY((pT1 <=> pT2) != 0);
+ EATEST_VERIFY((pT2 <=> pT1) != 0);
+
+ EATEST_VERIFY((pT1 <=> pT2) < 0);
+ EATEST_VERIFY((pT1 <=> pT2) <= 0);
+ EATEST_VERIFY((pT2 <=> pT1) > 0);
+ EATEST_VERIFY((pT2 <=> pT1) >= 0);
+
+ EATEST_VERIFY((pT3 <=> pT1) < 0);
+ EATEST_VERIFY((pT3 <=> pT2) < 0);
+ EATEST_VERIFY((pT1 <=> pT3) > 0);
+ EATEST_VERIFY((pT2 <=> pT3) > 0);
+
+ unique_ptr<A> pT4(new A(5));
+ unique_ptr<A> pT5(new A(10));
+
+ EATEST_VERIFY((pT4 <=> pT5) != 0);
+ EATEST_VERIFY((pT5 <=> pT4) != 0);
+
+ EATEST_VERIFY((pT4 <=> pT5) < 0);
+ EATEST_VERIFY((pT4 <=> pT5) <= 0);
+ EATEST_VERIFY((pT5 <=> pT4) > 0);
+ EATEST_VERIFY((pT5 <=> pT4) >= 0);
+ }
+ #endif
+
// ToDo: Test move assignment between two convertible types with an is_assignable deleter_type
//{
// struct Base {};
@@ -1351,7 +1384,7 @@ static int Test_shared_ptr()
{
EA::Thread::ThreadParameters mThreadParams;
EA::Thread::Thread mThread;
- volatile bool mbShouldContinue;
+ eastl::atomic<bool> mbShouldContinue;
int mnErrorCount;
eastl::shared_ptr<TestObject>* mpSPTO;
eastl::weak_ptr<TestObject>* mpWPTO;
@@ -1364,7 +1397,7 @@ static int Test_shared_ptr()
{
int& nErrorCount = mnErrorCount; // declare nErrorCount so that EATEST_VERIFY can work, as it depends on it being declared.
- while(mbShouldContinue)
+ while(mbShouldContinue.load(eastl::memory_order_relaxed))
{
EA::UnitTest::ThreadSleepRandom(1, 10);
@@ -1419,7 +1452,7 @@ static int Test_shared_ptr_thread()
EA::UnitTest::ThreadSleep(2000);
for(size_t i = 0; i < EAArrayCount(thread); i++)
- thread[i].mbShouldContinue = false;
+ thread[i].mbShouldContinue.store(false, eastl::memory_order_relaxed);
for(size_t i = 0; i < EAArrayCount(thread); i++)
{
diff --git a/EASTL/test/source/TestSort.cpp b/EASTL/test/source/TestSort.cpp
index 2d0116f..114a73b 100644
--- a/EASTL/test/source/TestSort.cpp
+++ b/EASTL/test/source/TestSort.cpp
@@ -177,8 +177,22 @@ namespace eastl
return x;
}
};
+
+ struct TestNoLessOperator
+ {
+ int i {};
+ };
} // namespace Internal
+ template <>
+ struct less<Internal::TestNoLessOperator>
+ {
+ bool operator()(const Internal::TestNoLessOperator& lhs, const Internal::TestNoLessOperator& rhs) const noexcept
+ {
+ return lhs.i < rhs.i;
+ }
+ };
+
} // namespace eastl
int TestSort()
@@ -630,6 +644,13 @@ int TestSort()
radix_sort<uint32_t*, identity_extract_radix_key<uint32_t>>(begin(input), end(input), buffer);
EATEST_VERIFY(is_sorted(begin(input), end(input)));
}
+ {
+ // Test case for bug where the last histogram bucket was not being cleared to zero
+ uint32_t input[] = { 0xff00, 0xff };
+ uint32_t buffer[EAArrayCount(input)];
+ radix_sort<uint32_t*, identity_extract_radix_key<uint32_t>>(begin(input), end(input), buffer);
+ EATEST_VERIFY(is_sorted(begin(input), end(input)));
+ }
}
{
@@ -793,7 +814,7 @@ int TestSort()
}
{
- // EATEST_VERIFY deque sorting can compile.
+ // Test checking that deque sorting can compile.
deque<int> intDeque;
vector<int> intVector;
@@ -801,6 +822,25 @@ int TestSort()
stable_sort(intVector.begin(), intVector.end());
}
+ {
+ // Test checking that sorting containers having elements of a type without an operator< compiles correctly
+
+ vector<TestNoLessOperator> noLessVector;
+
+ stable_sort(noLessVector.begin(), noLessVector.end());
+ bubble_sort(noLessVector.begin(), noLessVector.end());
+ shaker_sort(noLessVector.begin(), noLessVector.end());
+ insertion_sort(noLessVector.begin(), noLessVector.end());
+ selection_sort(noLessVector.begin(), noLessVector.end());
+ shell_sort(noLessVector.begin(), noLessVector.end());
+ comb_sort(noLessVector.begin(), noLessVector.end());
+ heap_sort(noLessVector.begin(), noLessVector.end());
+ merge_sort(noLessVector.begin(), noLessVector.end(), *get_default_allocator(nullptr));
+ quick_sort(noLessVector.begin(), noLessVector.end());
+
+ vector<TestNoLessOperator> buffer;
+ tim_sort_buffer(noLessVector.begin(), noLessVector.end(), buffer.data());
+}
{
// Test sorting of a container of pointers to objects as opposed to a container of objects themselves.
diff --git a/EASTL/test/source/TestSpan.cpp b/EASTL/test/source/TestSpan.cpp
index 060950d..5a0ec07 100644
--- a/EASTL/test/source/TestSpan.cpp
+++ b/EASTL/test/source/TestSpan.cpp
@@ -295,7 +295,7 @@ void TestSpanContainerConversion(int& nErrorCount)
{
vector<int> v = {0, 1, 2, 3, 4, 5};
- span<const int, 3> s1(v);
+ span<const int, 6> s1(v);
span<const int> s2(s1);
VERIFY(s2.size() == (span<const int>::index_type)v.size());
@@ -391,6 +391,24 @@ void TestSpanSubViews(int& nErrorCount)
VERIFY(first_span[3] == 9);
}
+ { // empty range
+ span<int, 0> s{};
+
+ auto fixed_span = s.subspan<0, 0>();
+ VERIFY(fixed_span.empty());
+ fixed_span = s.first<0>();
+ VERIFY(fixed_span.empty());
+ fixed_span = s.last<0>();
+ VERIFY(fixed_span.empty());
+
+ span<int> dynamic_span;
+ VERIFY(dynamic_span.empty());
+ dynamic_span = s.first(0);
+ VERIFY(dynamic_span.empty());
+ dynamic_span = s.last(0);
+ VERIFY(dynamic_span.empty());
+ }
+
{ // subspan: full range
span<int, 10> s = arr1;
diff --git a/EASTL/test/source/TestString.inl b/EASTL/test/source/TestString.inl
index 08fb924..3a59e68 100644
--- a/EASTL/test/source/TestString.inl
+++ b/EASTL/test/source/TestString.inl
@@ -2024,19 +2024,25 @@ 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'));
+ auto numErased = eastl::erase(str, LITERAL('a'));
+ VERIFY(numErased == 1);
+ numErased = eastl::erase(str, LITERAL('f'));
+ VERIFY(numErased == 1);
+ numErased = eastl::erase(str, LITERAL('l'));
+ VERIFY(numErased == 1);
+ numErased = eastl::erase(str, LITERAL('w'));
+ VERIFY(numErased == 1);
+ numErased = eastl::erase(str, LITERAL('y'));
+ VERIFY(numErased == 1);
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'); });
+ auto numErased = eastl::erase_if(str, [](auto c) { return c == LITERAL('a') || c == LITERAL('v'); });
VERIFY(str == LITERAL("bcdefghijklmnopqrstuwxyz"));
+ VERIFY(numErased == 2);
}
// template<> struct hash<eastl::string>;
@@ -2064,6 +2070,28 @@ int TEST_STRING_NAME()
VERIFY(LocalHash(sw2) == LocalHash(sw3));
}
+ // test <=> operator
+ #if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+ {
+ StringType sw1(LITERAL("Test String "));
+ StringType sw2(LITERAL("Test String 1"));
+ StringType sw3(LITERAL("Test String 2"));
+ StringType sw4(LITERAL("abcdef"));
+
+ VERIFY((sw1 <=> sw2) != 0);
+ VERIFY((sw1 <=> sw3) != 0);
+ VERIFY((sw2 <=> sw3) != 0);
+ VERIFY((sw1 <=> sw2) < 0);
+ VERIFY((sw1 <=> sw3) < 0);
+ VERIFY((sw2 <=> sw2) == 0);
+ VERIFY((sw2 <=> sw3) < 0);
+ VERIFY((sw2 <=> sw4) < 0);
+ VERIFY((sw4 <=> sw2) > 0);
+ VERIFY((sw4 <=> sw3) > 0);
+ VERIFY((sw3 <=> sw2) > 0);
+ }
+ #endif
+
return nErrorCount;
}
diff --git a/EASTL/test/source/TestStringView.cpp b/EASTL/test/source/TestStringView.cpp
index 835488c..23e6e51 100644
--- a/EASTL/test/source/TestStringView.cpp
+++ b/EASTL/test/source/TestStringView.cpp
@@ -5,6 +5,7 @@
#include "EASTLTest.h"
#include <EABase/eabase.h>
#include <EASTL/numeric_limits.h>
+#include <EASTL/string.h>
#include <EASTL/string_view.h>
// Verify char8_t support is present if the test build requested it.
@@ -78,12 +79,18 @@ int TestStringView()
static_assert(eastl::is_same_v<decltype(U"abcdef"_sv), eastl::u32string_view>, "string_view literal type mismatch");
static_assert(eastl::is_same_v<decltype(L"abcdef"_sv), eastl::wstring_view>, "string_view literal type mismatch");
- // TODO: Need to resolve this. Not sure why on Clang the user literal 'operator ""sv' can't be found.
- // VERIFY("cplusplus"sv.compare("cplusplus") == 0);
- // VERIFY(L"cplusplus"sv.compare(L"cplusplus") == 0);
- // VERIFY(u"cplusplus"sv.compare(u"cplusplus") == 0);
- // VERIFY(U"cplusplus"sv.compare(U"cplusplus") == 0);
- // VERIFY(u8"cplusplus"sv.compare(u8"cplusplus") == 0);
+
+ VERIFY("cplusplus"sv.compare("cplusplus") == 0);
+ VERIFY(L"cplusplus"sv.compare(L"cplusplus") == 0);
+ VERIFY(u"cplusplus"sv.compare(u"cplusplus") == 0);
+ VERIFY(U"cplusplus"sv.compare(U"cplusplus") == 0);
+ VERIFY(u8"cplusplus"sv.compare(u8"cplusplus") == 0);
+
+ static_assert(eastl::is_same_v<decltype("abcdef"sv), eastl::string_view>, "string_view literal type mismatch");
+ static_assert(eastl::is_same_v<decltype(u8"abcdef"sv), eastl::u8string_view>, "string_view literal type mismatch");
+ static_assert(eastl::is_same_v<decltype(u"abcdef"sv), eastl::u16string_view>, "string_view literal type mismatch");
+ static_assert(eastl::is_same_v<decltype(U"abcdef"sv), eastl::u32string_view>, "string_view literal type mismatch");
+ static_assert(eastl::is_same_v<decltype(L"abcdef"sv), eastl::wstring_view>, "string_view literal type mismatch");
}
#endif
diff --git a/EASTL/test/source/TestStringView.inl b/EASTL/test/source/TestStringView.inl
index 14472fb..cd4214e 100644
--- a/EASTL/test/source/TestStringView.inl
+++ b/EASTL/test/source/TestStringView.inl
@@ -5,6 +5,8 @@
template<typename StringViewT>
int TEST_STRING_NAME()
{
+ using StringT = eastl::basic_string<typename StringViewT::value_type>;
+
int nErrorCount = 0;
{
// EA_CONSTEXPR basic_string_view()
@@ -476,6 +478,84 @@ int TEST_STRING_NAME()
VERIFY(sw1 <= sw2);
VERIFY(sw2 > sw1);
VERIFY(sw2 >= sw1);
+
+#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+ VERIFY((sw1 <=> StringViewT(LITERAL("AAAAABBBBBCCCDDDDDEEEEEFFFGGH"))) == 0);
+ VERIFY((sw1 <=> StringViewT(LITERAL("abcdefghijklmnopqrstuvwxyz"))) != 0);
+ VERIFY((sw1 <=> sw2) < 0);
+ VERIFY((sw1 <=> sw2) <= 0);
+ VERIFY((sw2 <=> sw1) > 0);
+ VERIFY((sw2 <=> sw1) >= 0);
+#endif
+ }
+
+ {
+ auto s = LITERAL("Hello, World");
+ StringViewT sv(s);
+
+ VERIFY(s == sv);
+ VERIFY(sv == s);
+
+ VERIFY(s <= sv);
+ VERIFY(sv <= s);
+ VERIFY(s >= sv);
+ VERIFY(sv >= s);
+ VERIFY(!(s != sv));
+ VERIFY(!(sv != s));
+ VERIFY(!(s < sv));
+ VERIFY(!(sv < s));
+ VERIFY(!(s > sv));
+ VERIFY(!(sv > s));
+
+#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+ VERIFY((s <=> sv) == 0);
+ VERIFY((sv <=> s) == 0);
+
+ VERIFY((s <=> sv) <= 0);
+ VERIFY((sv <=> s) <= 0);
+ VERIFY((s <=> sv) >= 0);
+ VERIFY((sv <=> s) >= 0);
+ VERIFY(!((s <=> sv) != 0));
+ VERIFY(!((sv <=> s) != 0));
+ VERIFY(!((s <=> sv) > 0));
+ VERIFY(!((sv <=> s) < 0));
+#endif
+ }
+
+ // Regression comparison operators should work between basic_string_view and basic_string.
+ // The idea is that type_identity_t on some overloads will force basic_string::operator basic_string_view() to kick in.
+ {
+ StringT s(LITERAL("Hello, Stockholm"));
+ StringViewT sv(s);
+
+ VERIFY(s == sv);
+ VERIFY(sv == s);
+
+ // All the operators bellow used to not work.
+ VERIFY(s <= sv);
+ VERIFY(sv <= s);
+ VERIFY(s >= sv);
+ VERIFY(sv >= s);
+ VERIFY(!(s != sv));
+ VERIFY(!(sv != s));
+ VERIFY(!(s < sv));
+ VERIFY(!(sv < s));
+ VERIFY(!(s > sv));
+ VERIFY(!(sv > s));
+
+#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+ VERIFY((s <=> sv) == 0);
+ VERIFY((sv <=> s) == 0);
+
+ VERIFY((s <=> sv) <= 0);
+ VERIFY((sv <=> s) <= 0);
+ VERIFY((s <=> sv) >= 0);
+ VERIFY((sv <=> s) >= 0);
+ VERIFY(!((s <=> sv) != 0));
+ VERIFY(!((sv <=> s) != 0));
+ VERIFY(!((s <=> sv) > 0));
+ VERIFY(!((sv <=> s) < 0));
+#endif
}
// template<> struct hash<std::string_view>;
diff --git a/EASTL/test/source/TestTuple.cpp b/EASTL/test/source/TestTuple.cpp
index 8c1b48a..6a7647e 100644
--- a/EASTL/test/source/TestTuple.cpp
+++ b/EASTL/test/source/TestTuple.cpp
@@ -227,11 +227,27 @@ int TestTuple()
EATEST_VERIFY(aTuple != aDefaultInitTuple);
EATEST_VERIFY(aDefaultInitTuple < aTuple);
+ #if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+ EATEST_VERIFY((aTuple <=> anotherTuple) == 0);
+ EATEST_VERIFY((aTuple <=> anotherTuple) >= 0);
+ EATEST_VERIFY((anotherTuple <=> aTuple) >= 0);
+ EATEST_VERIFY((aTuple <=> aDefaultInitTuple) != 0);
+ EATEST_VERIFY((aDefaultInitTuple <=> aTuple) < 0);
+ #endif
+
tuple<int, int, int> lesserTuple(1, 2, 3);
tuple<int, int, int> greaterTuple(1, 2, 4);
EATEST_VERIFY(lesserTuple < greaterTuple && !(greaterTuple < lesserTuple) && greaterTuple > lesserTuple &&
!(lesserTuple > greaterTuple));
+ #if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+ EATEST_VERIFY((lesserTuple <=> greaterTuple) != 0);
+ EATEST_VERIFY((lesserTuple <=> greaterTuple) < 0);
+ EATEST_VERIFY((lesserTuple <=> greaterTuple) <= 0);
+ EATEST_VERIFY((greaterTuple <=> lesserTuple) > 0);
+ EATEST_VERIFY((greaterTuple <=> lesserTuple) >= 0);
+ #endif
+
tuple<int, float, TestObject> valTup(2, 2.0f, TestObject(2));
tuple<int&, float&, TestObject&> refTup(valTup);
tuple<const int&, const float&, const TestObject&> constRefTup(valTup);
@@ -272,6 +288,20 @@ int TestTuple()
}
{
+ // Test construction of tuple containing r-value references
+ int x = 42;
+ TestObject object{1337};
+
+ tuple<int&&, TestObject&&> aTupleWithRValueReference(eastl::move(x), eastl::move(object));
+ static_assert(is_same<decltype(get<0>(aTupleWithRValueReference)), int&>::value, "wrong return type for get when using r-value reference.");
+ static_assert(is_same<decltype(get<1>(aTupleWithRValueReference)), TestObject&>::value, "wrong return type for get when using r-value reference.");
+ EATEST_VERIFY(get<0>(aTupleWithRValueReference) == 42);
+ EATEST_VERIFY(get<1>(aTupleWithRValueReference).mX == 1337);
+
+ static_assert(!is_constructible<decltype(aTupleWithRValueReference), int&, TestObject&>::value, "it shouldn't be possible to assign r-value references with l-values.");
+ }
+
+ {
// Tuple helpers
// make_tuple
@@ -481,6 +511,27 @@ int TestTuple()
#endif
}
+ // Compilation test to make sure that we can handle reference to forward-declared types
+ {
+ struct ForwardDeclared;
+
+ auto fill_tuple = [](ForwardDeclared& f) {
+ eastl::tuple<ForwardDeclared&, const ForwardDeclared&> t{f, f};
+ return t;
+ };
+
+ struct ForwardDeclared
+ {
+ int x;
+ };
+
+ ForwardDeclared f{666};
+ auto t = fill_tuple(f);
+
+ EATEST_VERIFY(get<0>(t).x == 666);
+ EATEST_VERIFY(get<1>(t).x == 666);
+ }
+
#ifndef EA_COMPILER_NO_STRUCTURED_BINDING
// tuple structured bindings test
{
diff --git a/EASTL/test/source/TestTypeTraits.cpp b/EASTL/test/source/TestTypeTraits.cpp
index 0fb6280..2670e24 100644
--- a/EASTL/test/source/TestTypeTraits.cpp
+++ b/EASTL/test/source/TestTypeTraits.cpp
@@ -173,15 +173,16 @@ struct NonPod2
virtual void Function(){}
};
-#if EASTL_VARIABLE_TEMPLATES_ENABLED
- struct HasIncrementOperator { HasIncrementOperator& operator++() { return *this; } };
+struct HasIncrementOperator { HasIncrementOperator& operator++() { return *this; } };
- template<typename, typename = eastl::void_t<>>
- struct has_increment_operator : eastl::false_type {};
+template <class T>
+using has_increment_operator_detection = decltype(++eastl::declval<T>());
- template <typename T>
- struct has_increment_operator<T, eastl::void_t<decltype(++eastl::declval<T>())>> : eastl::true_type {};
-#endif
+template<typename, typename = eastl::void_t<>>
+struct has_increment_operator_using_void_t : eastl::false_type {};
+
+template <typename T>
+struct has_increment_operator_using_void_t<T, eastl::void_t<has_increment_operator_detection<T>>> : eastl::true_type {};
// We use this for the is_copy_constructible test in order to verify that
@@ -359,13 +360,19 @@ struct NonPolymorphic1
void Function(){}
};
+// Disable the following warning:
+// warning: ‘struct Abstract’ has virtual functions and accessible non-virtual destructor [-Wnon-virtual-dtor]
+// We explicitly want this class not to have a virtual destructor to test our type traits.
+EA_DISABLE_VC_WARNING(4265)
+EA_DISABLE_CLANG_WARNING(-Wnon-virtual-dtor)
+EA_DISABLE_GCC_WARNING(-Wnon-virtual-dtor)
struct Abstract
{
- #if defined(EA_COMPILER_GNUC) // GCC warns about this, so we include it for this class, even though for this compiler it partly defeats the purpose of its usage.
- virtual ~Abstract(){}
- #endif
virtual void Function() = 0;
};
+EA_RESTORE_GCC_WARNING()
+EA_RESTORE_CLANG_WARNING()
+EA_RESTORE_VC_WARNING()
struct AbstractWithDtor
{
@@ -542,6 +549,7 @@ int TestTypeTraits()
EATEST_VERIFY(GetType(is_integral<float>()) == false);
static_assert(is_integral<bool>::value, "is_integral failure");
+ static_assert(is_integral<char8_t>::value, "is_integral failure");
static_assert(is_integral<char16_t>::value, "is_integral failure");
static_assert(is_integral<char32_t>::value, "is_integral failure");
static_assert(is_integral<char>::value, "is_integral failure");
@@ -616,13 +624,55 @@ int TestTypeTraits()
EATEST_VERIFY(GetType(is_array<uint32_t*>()) == false);
+ //is_bounded_array
+ static_assert(is_bounded_array<Array>::value == true, "is_bounded_array failure");
+ EATEST_VERIFY(GetType(is_bounded_array<Array>()) == true);
+
+ static_assert(is_bounded_array<ArrayConst>::value == true, "is_bounded_array failure");
+ EATEST_VERIFY(GetType(is_bounded_array<ArrayConst>()) == true);
+
+ static_assert(is_bounded_array<int>::value == false, "is_bounded_array failure");
+ static_assert(is_bounded_array<int[32]>::value == true, "is_bounded_array failure");
+ static_assert(is_bounded_array<int[]>::value == false, "is_bounded_array failure");
+
+ static_assert(is_bounded_array<uint32_t>::value == false, "is_bounded_array failure");
+ EATEST_VERIFY(GetType(is_bounded_array<uint32_t>()) == false);
+
+ static_assert(is_bounded_array<uint32_t*>::value == false, "is_bounded_array failure");
+ EATEST_VERIFY(GetType(is_bounded_array<uint32_t*>()) == false);
+
+
+ //is_unbounded_array
+ static_assert(is_unbounded_array<Array>::value == false, "is_unbounded_array failure");
+ EATEST_VERIFY(GetType(is_unbounded_array<Array>()) == false);
+
+ static_assert(is_unbounded_array<ArrayConst>::value == false, "is_unbounded_array failure");
+ EATEST_VERIFY(GetType(is_unbounded_array<ArrayConst>()) == false);
+
+ static_assert(is_unbounded_array<int>::value == false, "is_unbounded_array failure");
+ static_assert(is_unbounded_array<int[32]>::value == false, "is_unbounded_array failure");
+ static_assert(is_unbounded_array<int[]>::value == true, "is_unbounded_array failure");
+
+ static_assert(is_unbounded_array<uint32_t>::value == false, "is_unbounded_array failure");
+ EATEST_VERIFY(GetType(is_unbounded_array<uint32_t>()) == false);
+
+ static_assert(is_unbounded_array<uint32_t*>::value == false, "is_unbounded_array failure");
+ EATEST_VERIFY(GetType(is_unbounded_array<uint32_t*>()) == false);
+
+
// is_reference
static_assert(is_reference<Class&>::value == true, "is_reference failure");
EATEST_VERIFY(GetType(is_reference<Class&>()) == true);
+ static_assert(is_reference<Class&&>::value == true, "is_reference failure");
+ EATEST_VERIFY(GetType(is_reference<Class&&>()) == true);
+
static_assert(is_reference<const Class&>::value == true, "is_reference failure");
EATEST_VERIFY(GetType(is_reference<const Class&>()) == true);
+ static_assert(is_reference<const Class&&>::value == true, "is_reference failure");
+ EATEST_VERIFY(GetType(is_reference<const Class&&>()) == true);
+
static_assert(is_reference<Class>::value == false, "is_reference failure");
EATEST_VERIFY(GetType(is_reference<Class>()) == false);
@@ -634,6 +684,10 @@ int TestTypeTraits()
static_assert(is_member_function_pointer<int>::value == false, "is_member_function_pointer failure");
static_assert(is_member_function_pointer<int(Class::*)>::value == false, "is_member_function_pointer failure");
static_assert(is_member_function_pointer<int(Class::*)()>::value == true, "is_member_function_pointer failure");
+ static_assert(is_member_function_pointer<int(Class::*)(...)>::value == true, "is_member_function_pointer failure");
+ static_assert(is_member_function_pointer<int(Class::*)() noexcept>::value == true, "is_member_function_pointer failure");
+ static_assert(is_member_function_pointer<int(Class::*)() &>::value == true, "is_member_function_pointer failure");
+ static_assert(is_member_function_pointer<int(Class::*)() &&>::value == true, "is_member_function_pointer failure");
// is_member_object_pointer
@@ -646,6 +700,9 @@ int TestTypeTraits()
static_assert(is_member_pointer<int>::value == false, "is_member_pointer failure");
static_assert(is_member_pointer<int(Class::*)>::value == true, "is_member_pointer failure");
static_assert(is_member_pointer<int(Class::*)()>::value == true, "is_member_pointer failure");
+ static_assert(is_member_pointer<int(Class::* const)>::value == true, "is_member_pointer failure");
+ static_assert(is_member_pointer<int(Class::* volatile)>::value == true, "is_member_pointer failure");
+ static_assert(is_member_pointer<int(Class::* const volatile)>::value == true, "is_member_pointer failure");
// is_pointer
@@ -674,6 +731,14 @@ int TestTypeTraits()
static_assert(is_enum_v<Class> == false, "is_enum failure ");
EATEST_VERIFY(GetType(is_enum<Class>()) == false);
+ static_assert(is_enum<Enum&>::value == false, "is_enum failure ");
+ static_assert(is_enum_v<Enum&> == false, "is_enum failure ");
+ EATEST_VERIFY(GetType(is_enum<Enum&>()) == false);
+
+ static_assert(is_enum<Enum&&>::value == false, "is_enum failure ");
+ static_assert(is_enum_v<Enum&&> == false, "is_enum failure ");
+ EATEST_VERIFY(GetType(is_enum<Enum&&>()) == false);
+
// is_union
static_assert(is_union<Union>::value == true, "is_union failure");
@@ -705,7 +770,7 @@ int TestTypeTraits()
// is_function
static_assert(is_function<void>::value == false, "is_function failure");
static_assert(is_function<FunctionVoidVoid>::value == true, "is_function failure");
- static_assert(is_function<FunctionVoidVoid&>::value == false, "is_function failure");
+ static_assert(is_function<FunctionVoidVoid&>::value == false, "is_function failure");
static_assert(is_function<FunctionIntVoid>::value == true, "is_function failure");
static_assert(is_function<FunctionIntFloat>::value == true, "is_function failure");
static_assert(is_function<FunctionVoidVoidPtr>::value == false, "is_function failure");
@@ -717,6 +782,16 @@ int TestTypeTraits()
// typedef int PrintfConst(const char*, ...) const;
static_assert(is_function<int (const char*, ...)>::value == true, "is_function failure"); // This is the signature of printf.
#endif
+
+ static_assert(is_function<int (float)>::value == true, "is_function failure");
+ static_assert(is_function<int (float) const>::value == true, "is_function failure");
+ static_assert(is_function<int(float) volatile>::value == true, "is_function failure");
+ static_assert(is_function<int(float) const volatile>::value == true, "is_function failure");
+ static_assert(is_function<int(float)&>::value == true, "is_function failure");
+ static_assert(is_function<int(float)&&>::value == true, "is_function failure");
+ static_assert(is_function<int(float) noexcept>::value == true, "is_function failure");
+ static_assert(is_function<FunctionIntFloat &>::value == false, "is_function failure"); // reference to function, not a l-value reference qualified function
+ static_assert(is_function<FunctionIntFloat &&>::value == false, "is_function failure");
static_assert(is_function_v<void> == false, "is_function failure");
static_assert(is_function_v<FunctionVoidVoid> == true, "is_function failure");
@@ -747,6 +822,9 @@ int TestTypeTraits()
static_assert(is_object<Class&>::value == false, "is_object failure");
EATEST_VERIFY(GetType(is_object<Class&>()) == false);
+ static_assert(is_object<Class&&>::value == false, "is_object failure");
+ EATEST_VERIFY(GetType(is_object<Class&&>()) == false);
+
// is_scalar
static_assert(is_scalar<int>::value == true, "is_scalar failure");
@@ -803,6 +881,8 @@ int TestTypeTraits()
static_assert(is_const<ConstVolatileIntReference>::value == false, "is_const failure"); // Note here that the int is const, not the reference to the int.
EATEST_VERIFY(GetType(is_const<ConstVolatileIntReference>()) == false);
+ static_assert(is_const<void() const>::value == false, "is_const failure");
+ EATEST_VERIFY(GetType(is_const<void() const>()) == false);
// is_volatile
static_assert(is_volatile<Int>::value == false, "is_volatile failure");
@@ -826,11 +906,26 @@ int TestTypeTraits()
static_assert(is_volatile<ConstVolatileIntReference>::value == false, "is_volatile failure"); // Note here that the int is volatile, not the reference to the int.
EATEST_VERIFY(GetType(is_volatile<ConstVolatileIntReference>()) == false);
+ static_assert(is_volatile<void() const>::value == false, "is_volatile failure");
+ EATEST_VERIFY(GetType(is_volatile<void() const>()) == false);
- // underlying_type
+
+ // underlying_type and to_underlying
#if EASTL_TYPE_TRAIT_underlying_type_CONFORMANCE && !defined(EA_COMPILER_NO_STRONGLY_TYPED_ENUMS) // If we can execute this test...
enum UnderlyingTypeTest : uint16_t { firstVal = 0, secondVal = 1 };
- static_assert(sizeof(underlying_type<UnderlyingTypeTest>::type) == sizeof(uint16_t), "underlying_type failure");
+
+ constexpr bool isUnderlyingTypeCorrect = is_same_v<underlying_type_t<UnderlyingTypeTest>, uint16_t>;
+ static_assert(isUnderlyingTypeCorrect, "Wrong type for underlying_type_t.");
+ EATEST_VERIFY(isUnderlyingTypeCorrect);
+
+ auto v1 = to_underlying(UnderlyingTypeTest::firstVal);
+ auto v2 = to_underlying(UnderlyingTypeTest::secondVal);
+
+ constexpr bool isToUnderlyingReturnTypeCorrect = is_same_v<decltype(v1), uint16_t>;
+ static_assert(isToUnderlyingReturnTypeCorrect, "Wrong return type for to_underlying.");
+ EATEST_VERIFY(isToUnderlyingReturnTypeCorrect);
+
+ EATEST_VERIFY(v1 == 0 && v2 == 1);
#endif
@@ -1038,7 +1133,24 @@ int TestTypeTraits()
static_assert(is_signed<double>::value == true, "is_signed failure ");
static_assert(is_signed_v<double> == true, "is_signed failure ");
EATEST_VERIFY(GetType(is_signed<double>()) == true);
-
+
+ static_assert(is_signed<char16_t>::value == false, "is_signed failure ");
+ static_assert(is_signed_v<char16_t> == false, "is_signed failure ");
+ EATEST_VERIFY(GetType(is_signed<char16_t>()) == false);
+
+ static_assert(is_signed<char32_t>::value == false, "is_signed failure ");
+ static_assert(is_signed_v<char32_t> == false, "is_signed failure ");
+ EATEST_VERIFY(GetType(is_signed<char32_t>()) == false);
+
+#if EASTL_GCC_STYLE_INT128_SUPPORTED
+ static_assert(is_signed<__int128_t>::value == true, "is_signed failure ");
+ static_assert(is_signed_v<__int128_t> == true, "is_signed failure ");
+ EATEST_VERIFY(GetType(is_signed<__int128_t>()) == true);
+
+ static_assert(is_signed<__uint128_t>::value == false, "is_signed failure ");
+ static_assert(is_signed_v<__uint128_t> == false, "is_signed failure ");
+ EATEST_VERIFY(GetType(is_signed<__uint128_t>()) == false);
+#endif
// is_unsigned
static_assert(is_unsigned<unsigned int>::value == true, "is_unsigned failure ");
@@ -1053,9 +1165,9 @@ int TestTypeTraits()
static_assert(is_unsigned_v<int32_t> == false, "is_unsigned failure ");
EATEST_VERIFY(GetType(is_unsigned<int32_t>()) == false);
- static_assert(is_unsigned<bool>::value == false, "is_unsigned failure ");
- static_assert(is_unsigned_v<bool> == false, "is_unsigned failure ");
- EATEST_VERIFY(GetType(is_unsigned<bool>()) == false);
+ static_assert(is_unsigned<bool>::value == true, "is_unsigned failure ");
+ static_assert(is_unsigned_v<bool> == true, "is_unsigned failure ");
+ EATEST_VERIFY(GetType(is_unsigned<bool>()) == true);
static_assert(is_unsigned<float>::value == false, "is_unsigned failure ");
static_assert(is_unsigned_v<float> == false, "is_unsigned failure ");
@@ -1064,6 +1176,24 @@ int TestTypeTraits()
static_assert(is_unsigned<double>::value == false, "is_unsigned failure ");
static_assert(is_unsigned_v<double> == false, "is_unsigned failure ");
EATEST_VERIFY(GetType(is_unsigned<double>()) == false);
+
+ static_assert(is_unsigned<char16_t>::value == true, "is_unsigned failure ");
+ static_assert(is_unsigned_v<char16_t> == true, "is_unsigned failure ");
+ EATEST_VERIFY(GetType(is_unsigned<char16_t>()) == true);
+
+ static_assert(is_unsigned<char32_t>::value == true, "is_unsigned failure ");
+ static_assert(is_unsigned_v<char32_t> == true, "is_unsigned failure ");
+ EATEST_VERIFY(GetType(is_unsigned<char32_t>()) == true);
+
+#if EASTL_GCC_STYLE_INT128_SUPPORTED
+ static_assert(is_unsigned<__int128_t>::value == false, "is_unsigned failure ");
+ static_assert(is_unsigned_v<__int128_t> == false, "is_unsigned failure ");
+ EATEST_VERIFY(GetType(is_unsigned<__int128_t>()) == false);
+
+ static_assert(is_unsigned<__uint128_t>::value == true, "is_unsigned failure ");
+ static_assert(is_unsigned_v<__uint128_t> == true, "is_unsigned failure ");
+ EATEST_VERIFY(GetType(is_unsigned<__uint128_t>()) == true);
+#endif
// is_lvalue_reference
@@ -1223,6 +1353,7 @@ int TestTypeTraits()
// is_trivially_copyable
static_assert(is_trivially_copyable<void>::value == false, "is_trivially_copyable failure");
+ EATEST_VERIFY(GetType(is_trivially_copyable<void>()) == false);
static_assert(is_trivially_copyable<int>::value == true, "is_trivially_copyable failure");
static_assert(is_trivially_copyable<int*>::value == true, "is_trivially_copyable failure");
static_assert(is_trivially_copyable<int[]>::value == true, "is_trivially_copyable failure");
@@ -1276,6 +1407,7 @@ int TestTypeTraits()
static_assert(is_constructible<const void>::value == false, "is_constructible failure");
static_assert(is_constructible<int>::value == true, "is_constructible failure");
static_assert(is_constructible<int&>::value == false, "is_constructible failure");
+ static_assert(is_constructible<int&&>::value == false, "is_constructible failure");
static_assert(is_constructible<int*>::value == true, "is_constructible failure");
static_assert(is_constructible<int[]>::value == false, "is_constructible failure");
static_assert(is_constructible<int[4]>::value == true, "is_constructible failure");
@@ -1365,14 +1497,16 @@ int TestTypeTraits()
// is_destructible
static_assert(is_destructible<int>::value == true, "is_destructible failure");
+ static_assert(is_destructible<int&>::value == true, "is_destructible failure");
+ static_assert(is_destructible<int&&>::value == true, "is_destructible failure");
static_assert(is_destructible<char>::value == true, "is_destructible failure");
static_assert(is_destructible<char*>::value == true, "is_destructible failure");
static_assert(is_destructible<PodA>::value == true, "is_destructible failure");
static_assert(is_destructible<void>::value == false, "is_destructible failure");
static_assert(is_destructible<int[3]>::value == true, "is_destructible failure");
static_assert(is_destructible<int[]>::value == false, "is_destructible failure"); // You can't call operator delete on this class.
- static_assert(is_destructible<Abstract>::value == false, "is_destructible failure"); // You can't call operator delete on this class.
- static_assert(is_destructible<AbstractWithDtor>::value == false, "is_destructible failure"); // You can't call operator delete on this class.
+ static_assert(is_destructible<Abstract>::value == true, "is_destructible failure");
+ static_assert(is_destructible<AbstractWithDtor>::value == true, "is_destructible failure");
#if !defined(EA_COMPILER_NO_DELETED_FUNCTIONS)
static_assert(is_destructible<DeletedDtor>::value == false, "is_destructible failure"); // You can't call operator delete on this class.
#endif
@@ -1381,6 +1515,8 @@ int TestTypeTraits()
// is_trivially_destructible
static_assert(is_trivially_destructible<int>::value == true, "is_trivially_destructible failure");
+ static_assert(is_trivially_destructible<int&>::value == true, "is_trivially_destructible failure");
+ static_assert(is_trivially_destructible<int&&>::value == true, "is_trivially_destructible failure");
static_assert(is_trivially_destructible<char>::value == true, "is_trivially_destructible failure");
static_assert(is_trivially_destructible<char*>::value == true, "is_trivially_destructible failure");
static_assert(is_trivially_destructible<void>::value == false, "is_trivially_destructible failure");
@@ -1388,16 +1524,25 @@ int TestTypeTraits()
static_assert(is_trivially_destructible<PodA>::value == true, "is_trivially_destructible failure");
static_assert(is_trivially_destructible<int[3]>::value == true, "is_trivially_destructible failure");
static_assert(is_trivially_destructible<int[]>::value == false, "is_trivially_destructible failure");
- static_assert(is_trivially_destructible<Abstract>::value == false, "is_trivially_destructible failure");
- static_assert(is_trivially_destructible<AbstractWithDtor>::value == false, "is_trivially_destructible failure");
+ static_assert(is_trivially_destructible<Abstract>::value == true, "is_trivially_destructible failure");
+ static_assert(is_trivially_destructible<AbstractWithDtor>::value == false, "is_trivially_destructible failure"); // Having a user-defined destructor make it non-trivial.
+ #if !defined(EA_COMPILER_NO_DELETED_FUNCTIONS)
static_assert(is_trivially_destructible<DeletedDtor>::value == false, "is_trivially_destructible failure");
+ #endif
static_assert(is_trivially_destructible<NonPod2>::value == false, "is_trivially_destructible failure"); // This case differs from is_destructible, because we have a declared destructor.
#endif
// is_nothrow_destructible
static_assert(is_nothrow_destructible<int>::value == true, "is_nothrow_destructible failure");
+ static_assert(is_nothrow_destructible<int&>::value == true, "is_nothrow_destructible failure");
+ static_assert(is_nothrow_destructible<int&&>::value == true, "is_nothrow_destructible failure");
static_assert(is_nothrow_destructible<void>::value == false, "is_nothrow_destructible failure");
+ static_assert(is_nothrow_destructible<Abstract>::value == true, "is_nothrow_destructible failure");
+ static_assert(is_nothrow_destructible<AbstractWithDtor>::value == true, "is_nothrow_destructible failure");
+ #if !defined(EA_COMPILER_NO_DELETED_FUNCTIONS)
+ static_assert(is_nothrow_destructible<DeletedDtor>::value == false, "is_nothrow_destructible failure"); // You can't call operator delete on this class.
+ #endif
#if EASTL_TYPE_TRAIT_is_nothrow_destructible_CONFORMANCE
static_assert(is_nothrow_destructible<NonPod2>::value == true, "is_nothrow_destructible failure"); // NonPod2 is nothrow destructible because it has an empty destructor (makes no calls) which has no exception specification. Thus its exception specification defaults to noexcept(true) [C++11 Standard, 15.4 paragraph 14]
static_assert(is_nothrow_destructible<NoThrowDestructible>::value == true, "is_nothrow_destructible failure");
@@ -1573,6 +1718,125 @@ int TestTypeTraits()
EATEST_VERIFY(u64 == UINT64_C(0xffffffffffffffff));
i64 = static_cast<eastl::make_signed<int64_t>::type>(u64);
EATEST_VERIFY(i64 == -1);
+
+
+ static_assert(eastl::is_same_v<signed char, eastl::make_signed<unsigned char>::type>);
+ static_assert(eastl::is_same_v<short, eastl::make_signed<unsigned short>::type>);
+ static_assert(eastl::is_same_v<int, eastl::make_signed<unsigned int>::type>);
+ static_assert(eastl::is_same_v<long, eastl::make_signed<unsigned long>::type>);
+ static_assert(eastl::is_same_v<long long, eastl::make_signed<unsigned long long>::type>);
+
+ static_assert(eastl::is_same_v<const signed char, eastl::make_signed<const unsigned char>::type>);
+ static_assert(eastl::is_same_v<const short, eastl::make_signed<const unsigned short>::type>);
+ static_assert(eastl::is_same_v<const int, eastl::make_signed<const unsigned int>::type>);
+ static_assert(eastl::is_same_v<const long, eastl::make_signed<const unsigned long>::type>);
+ static_assert(eastl::is_same_v<const long long, eastl::make_signed<const unsigned long long>::type>);
+
+ static_assert(eastl::is_same_v<volatile signed char, eastl::make_signed<volatile unsigned char>::type>);
+ static_assert(eastl::is_same_v<volatile short, eastl::make_signed<volatile unsigned short>::type>);
+ static_assert(eastl::is_same_v<volatile int, eastl::make_signed<volatile unsigned int>::type>);
+ static_assert(eastl::is_same_v<volatile long, eastl::make_signed<volatile unsigned long>::type>);
+ static_assert(eastl::is_same_v<volatile long long, eastl::make_signed<volatile unsigned long long>::type>);
+
+ static_assert(eastl::is_same_v<const volatile signed char, eastl::make_signed<const volatile unsigned char>::type>);
+ static_assert(eastl::is_same_v<const volatile short, eastl::make_signed<const volatile unsigned short>::type>);
+ static_assert(eastl::is_same_v<const volatile int, eastl::make_signed<const volatile unsigned int>::type>);
+ static_assert(eastl::is_same_v<const volatile long, eastl::make_signed<const volatile unsigned long>::type>);
+ static_assert(eastl::is_same_v<const volatile long long, eastl::make_signed<const volatile unsigned long long>::type>);
+
+ static_assert(eastl::is_same_v<unsigned char, eastl::make_unsigned<signed char>::type>);
+ static_assert(eastl::is_same_v<unsigned short, eastl::make_unsigned<short>::type>);
+ static_assert(eastl::is_same_v<unsigned int, eastl::make_unsigned<int>::type>);
+ static_assert(eastl::is_same_v<unsigned long, eastl::make_unsigned<long>::type>);
+ static_assert(eastl::is_same_v<unsigned long long, eastl::make_unsigned<long long>::type>);
+
+ static_assert(eastl::is_same_v<const unsigned char, eastl::make_unsigned<const signed char>::type>);
+ static_assert(eastl::is_same_v<const unsigned short, eastl::make_unsigned<const short>::type>);
+ static_assert(eastl::is_same_v<const unsigned int, eastl::make_unsigned<const int>::type>);
+ static_assert(eastl::is_same_v<const unsigned long, eastl::make_unsigned<const long>::type>);
+ static_assert(eastl::is_same_v<const unsigned long long, eastl::make_unsigned<const long long>::type>);
+
+ static_assert(eastl::is_same_v<volatile unsigned char, eastl::make_unsigned<volatile signed char>::type>);
+ static_assert(eastl::is_same_v<volatile unsigned short, eastl::make_unsigned<volatile short>::type>);
+ static_assert(eastl::is_same_v<volatile unsigned int, eastl::make_unsigned<volatile int>::type>);
+ static_assert(eastl::is_same_v<volatile unsigned long, eastl::make_unsigned<volatile long>::type>);
+ static_assert(eastl::is_same_v<volatile unsigned long long, eastl::make_unsigned<volatile long long>::type>);
+
+ static_assert(eastl::is_same_v<const volatile unsigned char, eastl::make_unsigned<const volatile signed char>::type>);
+ static_assert(eastl::is_same_v<const volatile unsigned short, eastl::make_unsigned<const volatile short>::type>);
+ static_assert(eastl::is_same_v<const volatile unsigned int, eastl::make_unsigned<const volatile int>::type>);
+ static_assert(eastl::is_same_v<const volatile unsigned long, eastl::make_unsigned<const volatile long>::type>);
+ static_assert(eastl::is_same_v<const volatile unsigned long long, eastl::make_unsigned<const volatile long long>::type>);
+
+ static_assert(eastl::is_same_v<signed char, eastl::make_signed<signed char>::type>);
+ static_assert(eastl::is_same_v<short, eastl::make_signed<signed short>::type>);
+ static_assert(eastl::is_same_v<int, eastl::make_signed<signed int>::type>);
+ static_assert(eastl::is_same_v<long, eastl::make_signed<signed long>::type>);
+ static_assert(eastl::is_same_v<long long, eastl::make_signed<signed long long>::type>);
+
+ static_assert(eastl::is_same_v<unsigned char, eastl::make_unsigned<unsigned char>::type>);
+ static_assert(eastl::is_same_v<unsigned short, eastl::make_unsigned<unsigned short>::type>);
+ static_assert(eastl::is_same_v<unsigned int, eastl::make_unsigned<unsigned int>::type>);
+ static_assert(eastl::is_same_v<unsigned long, eastl::make_unsigned<unsigned long>::type>);
+ static_assert(eastl::is_same_v<unsigned long long, eastl::make_unsigned<unsigned long long>::type>);
+
+ #if EASTL_GCC_STYLE_INT128_SUPPORTED
+ static_assert(eastl::is_same_v<__uint128_t, eastl::make_unsigned<__int128_t>::type>);
+ static_assert(eastl::is_same_v<__uint128_t, eastl::make_unsigned<__uint128_t>::type>);
+
+ static_assert(eastl::is_same_v<__int128_t, eastl::make_signed<__int128_t>::type>);
+ static_assert(eastl::is_same_v<__int128_t, eastl::make_signed<__uint128_t>::type>);
+ #endif
+
+ // Char tests
+ static_assert(sizeof(char) == sizeof(eastl::make_signed<char>::type));
+ static_assert(sizeof(wchar_t) == sizeof(eastl::make_signed<wchar_t>::type));
+ static_assert(sizeof(char8_t) == sizeof(eastl::make_signed<char8_t>::type));
+ static_assert(sizeof(char16_t) == sizeof(eastl::make_signed<char16_t>::type));
+ static_assert(sizeof(char32_t) == sizeof(eastl::make_signed<char32_t>::type));
+ static_assert(sizeof(char) == sizeof(eastl::make_unsigned<char>::type));
+ static_assert(sizeof(wchar_t) == sizeof(eastl::make_unsigned<wchar_t>::type));
+ static_assert(sizeof(char8_t) == sizeof(eastl::make_unsigned<char8_t>::type));
+ static_assert(sizeof(char16_t) == sizeof(eastl::make_unsigned<char16_t>::type));
+ static_assert(sizeof(char32_t) == sizeof(eastl::make_unsigned<char32_t>::type));
+
+ static_assert(eastl::is_same_v<signed char, eastl::make_signed<char8_t>::type>);
+ static_assert(eastl::is_same_v<unsigned char, eastl::make_unsigned<char8_t>::type>);
+
+ // Enum tests
+ enum EnumUCharSize : unsigned char {};
+ enum EnumUShortSize : unsigned short {};
+ enum EnumUIntSize : unsigned int {};
+ enum EnumULongSize : unsigned long {};
+ enum EnumULongLongSize : unsigned long long {};
+
+ static_assert(eastl::is_signed_v<eastl::make_signed<EnumUCharSize>::type>);
+ static_assert(eastl::is_signed_v<eastl::make_signed<EnumUShortSize>::type>);
+ static_assert(eastl::is_signed_v<eastl::make_signed<EnumUIntSize>::type>);
+ static_assert(eastl::is_signed_v<eastl::make_signed<EnumULongSize>::type>);
+ static_assert(eastl::is_signed_v<eastl::make_signed<EnumULongLongSize>::type>);
+ static_assert(sizeof(EnumUCharSize) == sizeof(eastl::make_signed<EnumUCharSize>::type));
+ static_assert(sizeof(EnumUShortSize) == sizeof(eastl::make_signed<EnumUShortSize>::type));
+ static_assert(sizeof(EnumUIntSize) == sizeof(eastl::make_signed<EnumUIntSize>::type));
+ static_assert(sizeof(EnumULongSize) == sizeof(eastl::make_signed<EnumULongSize>::type));
+ static_assert(sizeof(EnumULongLongSize) == sizeof(eastl::make_signed<EnumULongLongSize>::type));
+
+ enum EnumCharSize : signed char {};
+ enum EnumShortSize : short {};
+ enum EnumIntSize : int {};
+ enum EnumLongSize : long {};
+ enum EnumLongLongSize : long long {};
+
+ static_assert(eastl::is_unsigned_v<eastl::make_unsigned<EnumCharSize>::type>);
+ static_assert(eastl::is_unsigned_v<eastl::make_unsigned<EnumShortSize>::type>);
+ static_assert(eastl::is_unsigned_v<eastl::make_unsigned<EnumIntSize>::type>);
+ static_assert(eastl::is_unsigned_v<eastl::make_unsigned<EnumLongSize>::type>);
+ static_assert(eastl::is_unsigned_v<eastl::make_unsigned<EnumLongLongSize>::type>);
+ static_assert(sizeof(EnumCharSize) == sizeof(eastl::make_unsigned<EnumCharSize>::type));
+ static_assert(sizeof(EnumShortSize) == sizeof(eastl::make_unsigned<EnumShortSize>::type));
+ static_assert(sizeof(EnumIntSize) == sizeof(eastl::make_unsigned<EnumIntSize>::type));
+ static_assert(sizeof(EnumLongSize) == sizeof(eastl::make_unsigned<EnumLongSize>::type));
+ static_assert(sizeof(EnumLongLongSize) == sizeof(eastl::make_unsigned<EnumLongLongSize>::type));
}
// remove_const
@@ -1685,6 +1949,28 @@ int TestTypeTraits()
yValue = 3;
EATEST_VERIFY(yValue == 3);
+ // ref to T
+ // -> T*
+ static_assert(is_same_v<add_pointer_t<int&>, int*>, "add_pointer failure");
+ static_assert(is_same_v<add_pointer_t<int(&)()>, int(*)()>, "add_pointer failure");
+
+ // object type (a (possibly cv-qualified) type other than function type, reference type or void), or
+ // a function type that is not cv- or ref-qualified, or a (possibly cv-qualified) void type
+ // -> T*
+ static_assert(is_same_v<add_pointer_t<int>, int*>, "add_pointer failure");
+ static_assert(is_same_v<add_pointer_t<int*>, int**>, "add_pointer failure");
+ static_assert(is_same_v<add_pointer_t<int()>, int(*)()>, "add_pointer failure");
+ static_assert(is_same_v<add_pointer_t<void>, void*>, "add_pointer failure");
+ static_assert(is_same_v<add_pointer_t<const void>, const void*>, "add_pointer failure");
+ static_assert(is_same_v<add_pointer_t<volatile void>, volatile void*>, "add_pointer failure");
+ static_assert(is_same_v<add_pointer_t<const volatile void>, const volatile void*>, "add_pointer failure");
+
+ // otherwise (cv- or ref-qualified function type)
+ // -> T
+ static_assert(is_same_v<add_pointer_t<int() const>, int() const>, "add_pointer failure");
+ static_assert(is_same_v<add_pointer_t<int() volatile>, int() volatile>, "add_pointer failure");
+ static_assert(is_same_v<add_pointer_t<int() const volatile>, int() const volatile>, "add_pointer failure");
+
// remove_extent
// If T is an array of some type X, provides the member typedef type equal to X, otherwise
// type is T. Note that if T is a multidimensional array, only the first dimension is removed.
@@ -1698,6 +1984,55 @@ int TestTypeTraits()
static_assert((eastl::is_same<Int2, int>::value == true), "remove_all_extents/is_same failure");
}
+ // add_lvalue_reference
+ {
+ // function type with no cv- or ref-qualifier
+ // -> T&
+ static_assert(is_same_v<add_lvalue_reference_t<void()>, void(&)()>, "add_lvalue_reference failure");
+
+ // object type (a (possibly cv-qualified) type other than function type, reference type or void)
+ // -> T&
+ static_assert(is_same_v<add_lvalue_reference_t<int>, int&>, "add_lvalue_reference failure");
+ static_assert(is_same_v<add_lvalue_reference_t<const int>, const int&>, "add_lvalue_reference failure");
+
+ // if T is an rvalue reference (to some type U)
+ // -> U&
+ static_assert(is_same_v<add_lvalue_reference_t<int&&>, int&>, "add_lvalue_reference failure");
+
+ // otherwise (cv- or ref-qualified function type, or reference type, or (possibly cv-qualified) void)
+ // -> T
+ static_assert(is_same_v<add_lvalue_reference_t<void() const>, void() const>, "add_lvalue_reference failure");
+ static_assert(is_same_v<add_lvalue_reference_t<void()&>, void()&>, "add_lvalue_reference failure");
+ static_assert(is_same_v<add_lvalue_reference_t<void()&&>, void()&&>, "add_lvalue_reference failure");
+ static_assert(is_same_v<add_lvalue_reference_t<int&>, int&>, "add_lvalue_reference failure");
+ static_assert(is_same_v<add_lvalue_reference_t<const int&>, const int&>, "add_lvalue_reference failure");
+ static_assert(is_same_v<add_lvalue_reference_t<void>, void>, "add_lvalue_reference failure");
+ static_assert(is_same_v<add_lvalue_reference_t<const void>, const void>, "add_lvalue_reference failure");
+ }
+
+ // add_rvalue_reference
+ {
+ // function type with no cv- or ref-qualifier
+ // -> T&&
+ static_assert(is_same_v<add_rvalue_reference_t<void()>, void(&&)()>, "add_rvalue_reference failure");
+
+ // object type (a (possibly cv-qualified) type other than function type, reference type or void)
+ // -> T&&
+ static_assert(is_same_v<add_rvalue_reference_t<int>, int&&>, "add_rvalue_reference failure");
+ static_assert(is_same_v<add_rvalue_reference_t<const int>, const int&&>, "add_rvalue_reference failure");
+
+ // otherwise (cv- or ref-qualified function type, or reference type, or (possibly cv-qualified) void)
+ // -> T
+ static_assert(is_same_v<add_rvalue_reference_t<void() const>, void() const>, "add_rvalue_reference failure");
+ static_assert(is_same_v<add_rvalue_reference_t<void()&>, void()&>, "add_rvalue_reference failure");
+ static_assert(is_same_v<add_rvalue_reference_t<void()&&>, void()&&>, "add_rvalue_reference failure");
+ static_assert(is_same_v<add_rvalue_reference_t<int&>, int&>, "add_rvalue_reference failure");
+ static_assert(is_same_v<add_rvalue_reference_t<int&&>, int&&>, "add_rvalue_reference failure");
+ static_assert(is_same_v<add_rvalue_reference_t<const int&>, const int&>, "add_rvalue_reference failure");
+ static_assert(is_same_v<add_rvalue_reference_t<void>, void>, "add_rvalue_reference failure");
+ static_assert(is_same_v<add_rvalue_reference_t<const void>, const void>, "add_rvalue_reference failure");
+ }
+
// decay
{
@@ -1831,26 +2166,71 @@ int TestTypeTraits()
}
// void_t
- #if EASTL_VARIABLE_TEMPLATES_ENABLED
{
{
- static_assert(is_same_v<void_t<void>, void>, "void_t failure");
- static_assert(is_same_v<void_t<int>, void>, "void_t failure");
- static_assert(is_same_v<void_t<short>, void>, "void_t failure");
- static_assert(is_same_v<void_t<long>, void>, "void_t failure");
- static_assert(is_same_v<void_t<long long>, void>, "void_t failure");
- static_assert(is_same_v<void_t<ClassEmpty>, void>, "void_t failure");
- static_assert(is_same_v<void_t<ClassNonEmpty>, void>, "void_t failure");
- static_assert(is_same_v<void_t<vector<int>>, void>, "void_t failure");
+ static_assert(is_same<void_t<void>, void>::value, "void_t failure");
+ static_assert(is_same<void_t<int>, void>::value, "void_t failure");
+ static_assert(is_same<void_t<short>, void>::value, "void_t failure");
+ static_assert(is_same<void_t<long>, void>::value, "void_t failure");
+ static_assert(is_same<void_t<long long>, void>::value, "void_t failure");
+ static_assert(is_same<void_t<ClassEmpty>, void>::value, "void_t failure");
+ static_assert(is_same<void_t<ClassNonEmpty>, void>::value, "void_t failure");
+ static_assert(is_same<void_t<vector<int>>, void>::value, "void_t failure");
}
// new sfinae mechansim test
{
- static_assert(has_increment_operator<HasIncrementOperator>::value, "void_t sfinae failure");
- static_assert(!has_increment_operator<ClassEmpty>::value, "void_t sfinae failure");
+ static_assert(has_increment_operator_using_void_t<HasIncrementOperator>::value, "void_t sfinae failure");
+ static_assert(!has_increment_operator_using_void_t<ClassEmpty>::value, "void_t sfinae failure");
}
}
+
+ // detected idiom
+ {
+ static_assert(is_detected<has_increment_operator_detection, HasIncrementOperator>::value, "is_detected failure.");
+ static_assert(!is_detected<has_increment_operator_detection, ClassEmpty>::value, "is_detected failure.");
+
+ static_assert(is_same<detected_t<has_increment_operator_detection, HasIncrementOperator>, HasIncrementOperator&>::value, "is_detected_t failure.");
+ static_assert(is_same<detected_t<has_increment_operator_detection, ClassEmpty>, nonesuch>::value, "is_detected_t failure.");
+
+ using detected_or_positive_result = detected_or<float, has_increment_operator_detection, HasIncrementOperator>;
+ using detected_or_negative_result = detected_or<float, has_increment_operator_detection, ClassEmpty>;
+ static_assert(detected_or_positive_result::value_t::value, "detected_or failure.");
+ static_assert(!detected_or_negative_result::value_t::value, "detected_or failure.");
+ static_assert(is_same<detected_or_positive_result::type, HasIncrementOperator&>::value, "detected_or failure.");
+ static_assert(is_same<detected_or_negative_result::type, float>::value, "detected_or failure.");
+
+ static_assert(is_same<detected_or_t<float, has_increment_operator_detection, HasIncrementOperator>, HasIncrementOperator&>::value, "detected_or_t failure.");
+ static_assert(is_same<detected_or_t<float, has_increment_operator_detection, ClassEmpty>, float>::value, "detected_or_t failure.");
+
+ static_assert(is_detected_exact<HasIncrementOperator&, has_increment_operator_detection, HasIncrementOperator>::value, "is_detected_exact failure.");
+ static_assert(!is_detected_exact<float, has_increment_operator_detection, HasIncrementOperator>::value, "is_detected_exact failure.");
+ static_assert(is_detected_exact<nonesuch, has_increment_operator_detection, ClassEmpty>::value, "is_detected_exact failure.");
+ static_assert(!is_detected_exact<float, has_increment_operator_detection, ClassEmpty>::value, "is_detected_exact failure.");
+
+ static_assert(is_detected_convertible<HasIncrementOperator&, has_increment_operator_detection, HasIncrementOperator>::value, "is_detected_convertible failure.");
+ static_assert(is_detected_convertible<HasIncrementOperator, has_increment_operator_detection, HasIncrementOperator>::value, "is_detected_convertible failure.");
+ static_assert(!is_detected_convertible<float, has_increment_operator_detection, HasIncrementOperator>::value, "is_detected_convertible failure.");
+ static_assert(!is_detected_convertible<nonesuch, has_increment_operator_detection, ClassEmpty>::value, "is_detected_convertible failure.");
+ static_assert(!is_detected_convertible<float, has_increment_operator_detection, ClassEmpty>::value, "is_detected_convertible failure.");
+
+
+ #if EASTL_VARIABLE_TEMPLATES_ENABLED
+ static_assert(is_detected_v<has_increment_operator_detection, HasIncrementOperator>, "is_detected_v failure.");
+ static_assert(!is_detected_v<has_increment_operator_detection, ClassEmpty>, "is_detected_v failure.");
+
+ static_assert(is_detected_exact_v<HasIncrementOperator&, has_increment_operator_detection, HasIncrementOperator>, "is_detected_exact_v failure.");
+ static_assert(!is_detected_exact_v<float, has_increment_operator_detection, HasIncrementOperator>, "is_detected_exact_v failure.");
+ static_assert(is_detected_exact_v<nonesuch, has_increment_operator_detection, ClassEmpty>, "is_detected_exact_v failure.");
+ static_assert(!is_detected_exact_v<float, has_increment_operator_detection, ClassEmpty>, "is_detected_exact_v failure.");
+
+ static_assert(is_detected_convertible_v<HasIncrementOperator&, has_increment_operator_detection, HasIncrementOperator>, "is_detected_convertible_v failure.");
+ static_assert(is_detected_convertible_v<HasIncrementOperator, has_increment_operator_detection, HasIncrementOperator>, "is_detected_convertible_v failure.");
+ static_assert(!is_detected_convertible_v<float, has_increment_operator_detection, HasIncrementOperator>, "is_detected_convertible_v failure.");
+ static_assert(!is_detected_convertible_v<nonesuch, has_increment_operator_detection, ClassEmpty>, "is_detected_convertible_v failure.");
+ static_assert(!is_detected_convertible_v<float, has_increment_operator_detection, ClassEmpty>, "is_detected_convertible_v failure.");
#endif
+ }
// conjunction
{
@@ -2012,8 +2392,10 @@ int TestTypeTraits()
static_assert(!is_aggregate_v<NotAggregrate>, "is_aggregate failure");
}
- #ifndef EA_COMPILER_MSVC
- // NOTE(rparolin): MSVC is incorrectly categorizing the aggregate type in this test-case.
+ #if defined(EA_COMPILER_CPP11_ENABLED) && !defined(EA_COMPILER_CPP14_ENABLED)
+ // See https://en.cppreference.com/w/cpp/language/aggregate_initialization
+ // In C++11 the requirement was added to aggregate types that no default member initializers exist,
+ // however this requirement was removed in C++14.
{
struct NotAggregrate { int data = 42; }; // default member initializer
static_assert(!is_aggregate_v<NotAggregrate>, "is_aggregate failure");
@@ -2027,12 +2409,31 @@ int TestTypeTraits()
}
#endif
- return nErrorCount;
-}
-
+ // is_complete_type
+ {
+ struct Foo
+ {
+ int x;
+ };
+ struct FooEmpty
+ {
+ };
+ struct Bar;
+ void FooFunc();
+ static_assert(eastl::internal::is_complete_type_v<Foo>, "is_complete_type failure");
+ static_assert(eastl::internal::is_complete_type_v<FooEmpty>, "is_complete_type failure");
+ static_assert(!eastl::internal::is_complete_type_v<Bar>, "is_complete_type failure");
+ static_assert(!eastl::internal::is_complete_type_v<void>, "is_complete_type failure");
+ static_assert(!eastl::internal::is_complete_type_v<volatile void>, "is_complete_type failure");
+ static_assert(!eastl::internal::is_complete_type_v<const void>, "is_complete_type failure");
+ static_assert(!eastl::internal::is_complete_type_v<const volatile void>, "is_complete_type failure");
+ static_assert(eastl::internal::is_complete_type_v<decltype(FooFunc)>, "is_complete_type failure");
+ }
+ return nErrorCount;
+}
diff --git a/EASTL/test/source/TestUtility.cpp b/EASTL/test/source/TestUtility.cpp
index 363f409..e9027e5 100644
--- a/EASTL/test/source/TestUtility.cpp
+++ b/EASTL/test/source/TestUtility.cpp
@@ -108,7 +108,7 @@ static int TestUtilityPair()
EATEST_VERIFY((p2.first == 0) && (p2.second == 1.f));
pair<const char*, int> p3 = eastl::make_pair("a", 1);
- EATEST_VERIFY((EA::StdC::Strcmp(p3.first, "a") == 0) && (p2.second == 1));
+ EATEST_VERIFY((EA::StdC::Strcmp(p3.first, "a") == 0) && (p3.second == 1));
pair<const char*, int> p4 = eastl::make_pair<const char*, int>("a", 1);
EATEST_VERIFY((EA::StdC::Strcmp(p4.first, "a") == 0) && (p4.second == 1));
@@ -116,6 +116,20 @@ static int TestUtilityPair()
pair<int, const char*> p5 = eastl::make_pair<int, const char*>(1, "b");
EATEST_VERIFY((p5.first == 1) && (EA::StdC::Strcmp(p5.second, "b") == 0));
+#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+ pair<int, int> p6 = eastl::make_pair<int, int>(1, 2);
+ pair<int, int> p7 = eastl::make_pair<int, int>(2, 1);
+ pair<int, int> p8 = eastl::make_pair<int, int>(7, 8);
+ pair<int, int> p9 = eastl::make_pair<int, int>(10, 1);
+
+ EATEST_VERIFY( (p6 <=> p7) != 0);
+ EATEST_VERIFY( (p6 <=> p6) == 0);
+ EATEST_VERIFY( (p7 <=> p8) < 0);
+ EATEST_VERIFY( (p7 <=> p8) <= 0);
+ EATEST_VERIFY( (p9 <=> p8) > 0);
+ EATEST_VERIFY( (p9 <=> p8) >= 0);
+#endif
+
#if !defined(EA_COMPILER_NO_AUTO)
auto p60 = eastl::make_pair("a", "b"); // Different strings of same length of 1.
EATEST_VERIFY((EA::StdC::Strcmp(p60.first, "a") == 0) && (EA::StdC::Strcmp(p60.second, "b") == 0));
@@ -495,13 +509,15 @@ static int TestUtilityIntegerSequence()
using namespace eastl;
int nErrorCount = 0;
#if EASTL_VARIADIC_TEMPLATES_ENABLED
-// Android clang chokes with an internal compiler error on make_integer_sequence
-#if !defined(EA_PLATFORM_ANDROID)
+
EATEST_VERIFY((integer_sequence<int, 0, 1, 2, 3, 4>::size() == 5));
EATEST_VERIFY((make_integer_sequence<int, 5>::size() == 5));
-#endif
+ static_assert(is_same<make_integer_sequence<int, 5>, integer_sequence<int, 0, 1, 2, 3, 4>>::value);
+
EATEST_VERIFY((index_sequence<0, 1, 2, 3, 4>::size() == 5));
EATEST_VERIFY((make_index_sequence<5>::size() == 5));
+ static_assert(is_same<make_index_sequence<5>, index_sequence<0, 1, 2, 3, 4>>::value);
+ static_assert(is_same<make_index_sequence<5>, integer_sequence<size_t, 0, 1, 2, 3, 4>>::value);
#endif // EASTL_VARIADIC_TEMPLATES_ENABLED
return nErrorCount;
@@ -614,6 +630,271 @@ static int TestUtilityExchange()
return nErrorCount;
}
+#if defined(EA_COMPILER_CPP20_ENABLED)
+template <typename T>
+static int TestCmpCommon()
+{
+ int nErrorCount = 0;
+
+ EATEST_VERIFY(eastl::cmp_equal(T(0), T(0)));
+ EATEST_VERIFY(eastl::cmp_equal(T(1), T(1)));
+ EATEST_VERIFY(eastl::cmp_equal(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::min()));
+ EATEST_VERIFY(eastl::cmp_equal(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::max()));
+ EATEST_VERIFY(!eastl::cmp_equal(T(0), T(1)));
+ EATEST_VERIFY(!eastl::cmp_equal(T(1), T(0)));
+ if (eastl::is_signed_v<T>)
+ {
+ EATEST_VERIFY(eastl::cmp_equal(T(-1), T(-1)));
+ EATEST_VERIFY(!eastl::cmp_equal(T(-1), T(-2)));
+ EATEST_VERIFY(!eastl::cmp_equal(T(-2), T(-1)));
+ }
+
+ EATEST_VERIFY(eastl::cmp_not_equal(T(1), T(0)));
+ EATEST_VERIFY(eastl::cmp_not_equal(T(0), T(1)));
+ EATEST_VERIFY(eastl::cmp_not_equal(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::max()));
+ EATEST_VERIFY(eastl::cmp_not_equal(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::min()));
+ if (eastl::is_signed_v<T>)
+ {
+ EATEST_VERIFY(!eastl::cmp_not_equal(T(-1), T(-1)));
+ EATEST_VERIFY(eastl::cmp_not_equal(T(-1), T(-2)));
+ EATEST_VERIFY(eastl::cmp_not_equal(T(-2), T(-1)));
+ }
+
+ EATEST_VERIFY(eastl::cmp_less(T(0), T(1)));
+ EATEST_VERIFY(eastl::cmp_less(T(5), T(10)));
+ EATEST_VERIFY(!eastl::cmp_less(T(0), T(0)));
+ EATEST_VERIFY(!eastl::cmp_less(T(1), T(0)));
+ EATEST_VERIFY(eastl::cmp_less(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::max()));
+ EATEST_VERIFY(!eastl::cmp_less(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::min()));
+ EATEST_VERIFY(!eastl::cmp_less(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::max()));
+ EATEST_VERIFY(!eastl::cmp_less(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::min()));
+ if (eastl::is_signed_v<T>)
+ {
+ EATEST_VERIFY(!eastl::cmp_less(T(-1), T(-1)));
+ EATEST_VERIFY(!eastl::cmp_less(T(-1), T(-2)));
+ EATEST_VERIFY(eastl::cmp_less(T(-2), T(-1)));
+ }
+
+ EATEST_VERIFY(eastl::cmp_less_equal(T(0), T(1)));
+ EATEST_VERIFY(eastl::cmp_less_equal(T(5), T(10)));
+ EATEST_VERIFY(eastl::cmp_less_equal(T(0), T(0)));
+ EATEST_VERIFY(eastl::cmp_less_equal(T(1), T(1)));
+ EATEST_VERIFY(!eastl::cmp_less_equal(T(1), T(0)));
+ EATEST_VERIFY(eastl::cmp_less_equal(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::max()));
+ EATEST_VERIFY(eastl::cmp_less_equal(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::min()));
+ EATEST_VERIFY(eastl::cmp_less_equal(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::max()));
+ EATEST_VERIFY(!eastl::cmp_less_equal(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::min()));
+ if (eastl::is_signed_v<T>)
+ {
+ EATEST_VERIFY(eastl::cmp_less_equal(T(-1), T(-1)));
+ EATEST_VERIFY(!eastl::cmp_less_equal(T(-1), T(-2)));
+ EATEST_VERIFY(eastl::cmp_less_equal(T(-2), T(-1)));
+ }
+
+ EATEST_VERIFY(eastl::cmp_greater(T(1), T(0)));
+ EATEST_VERIFY(eastl::cmp_greater(T(10), T(5)));
+ EATEST_VERIFY(!eastl::cmp_greater(T(0), T(0)));
+ EATEST_VERIFY(!eastl::cmp_greater(T(0), T(1)));
+ EATEST_VERIFY(eastl::cmp_greater(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::min()));
+ EATEST_VERIFY(!eastl::cmp_greater(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::min()));
+ EATEST_VERIFY(!eastl::cmp_greater(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::max()));
+ EATEST_VERIFY(!eastl::cmp_greater(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::max()));
+ if (eastl::is_signed_v<T>)
+ {
+ EATEST_VERIFY(!eastl::cmp_greater(T(-1), T(-1)));
+ EATEST_VERIFY(eastl::cmp_greater(T(-1), T(-2)));
+ EATEST_VERIFY(!eastl::cmp_greater(T(-2), T(-1)));
+ }
+
+ EATEST_VERIFY(eastl::cmp_greater_equal(T(1), T(0)));
+ EATEST_VERIFY(eastl::cmp_greater_equal(T(10), T(5)));
+ EATEST_VERIFY(eastl::cmp_greater_equal(T(0), T(0)));
+ EATEST_VERIFY(!eastl::cmp_greater_equal(T(0), T(1)));
+ EATEST_VERIFY(eastl::cmp_greater_equal(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::min()));
+ EATEST_VERIFY(eastl::cmp_greater_equal(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::min()));
+ EATEST_VERIFY(eastl::cmp_greater_equal(eastl::numeric_limits<T>::max(), eastl::numeric_limits<T>::max()));
+ EATEST_VERIFY(!eastl::cmp_greater_equal(eastl::numeric_limits<T>::min(), eastl::numeric_limits<T>::max()));
+ if (eastl::is_signed_v<T>)
+ {
+ EATEST_VERIFY(eastl::cmp_greater_equal(T(-1), T(-1)));
+ EATEST_VERIFY(eastl::cmp_greater_equal(T(-1), T(-2)));
+ EATEST_VERIFY(!eastl::cmp_greater_equal(T(-2), T(-1)));
+ }
+
+ return nErrorCount;
+}
+
+template <typename T, typename U>
+static int TestUtilityCmpEql(const T x, const U y)
+{
+ int nErrorCount = 0;
+
+ EATEST_VERIFY(eastl::cmp_equal(T(x), U(y)));
+ EATEST_VERIFY(eastl::cmp_equal(U(y), T(x)));
+ EATEST_VERIFY(!eastl::cmp_not_equal(T(x), U(y)));
+ EATEST_VERIFY(!eastl::cmp_not_equal(U(y), T(x)));
+
+ return nErrorCount;
+}
+
+template <typename T, typename U>
+static int TestUtilityCmpLess(const T x, const U y)
+{
+ int nErrorCount = 0;
+
+ EATEST_VERIFY(eastl::cmp_less(T(x), U(y)));
+ EATEST_VERIFY(!eastl::cmp_less(U(y), T(x)));
+
+ EATEST_VERIFY(!eastl::cmp_greater_equal(T(x), U(y)));
+ EATEST_VERIFY(eastl::cmp_greater_equal(U(y), T(x)));
+
+ return nErrorCount;
+}
+
+template <typename T, typename U>
+static int TestUtilityCmpGreater(const T x, const U y)
+{
+ int nErrorCount = 0;
+
+ EATEST_VERIFY(eastl::cmp_greater(T(x), U(y)));
+ EATEST_VERIFY(!eastl::cmp_greater(U(y), T(x)));
+
+ EATEST_VERIFY(!eastl::cmp_less_equal(T(x), U(y)));
+ EATEST_VERIFY(eastl::cmp_less_equal(U(y), T(x)));
+
+ return nErrorCount;
+}
+
+template <typename T, typename U>
+static int TestUtilityCmpLessEq(const T x, const U y)
+{
+ int nErrorCount = 0;
+
+ EATEST_VERIFY(eastl::cmp_less_equal(T(x), U(y)));
+ EATEST_VERIFY(eastl::cmp_less(T(x), U(y)) || eastl::cmp_equal(T(x), U(y)));
+
+ EATEST_VERIFY(eastl::cmp_greater_equal(U(y), T(x)));
+
+ return nErrorCount;
+}
+
+template <typename T, typename U>
+static int TestUtilityCmpGreaterEq(const T x, const U y)
+{
+ int nErrorCount = 0;
+
+ EATEST_VERIFY(eastl::cmp_greater_equal(T(x), U(y)));
+ EATEST_VERIFY(eastl::cmp_greater(T(x), U(y)) || eastl::cmp_equal(T(x), U(y)));
+
+ EATEST_VERIFY(eastl::cmp_less_equal(U(y), T(x)));
+
+ return nErrorCount;
+}
+
+static int TestUtilityIntegralComp()
+{
+ int nErrorCount = 0;
+
+ // Test integral comparisons among same types
+ nErrorCount += TestCmpCommon<int>();
+ nErrorCount += TestCmpCommon<short>();
+ nErrorCount += TestCmpCommon<long>();
+ nErrorCount += TestCmpCommon<long long>();
+
+ nErrorCount += TestCmpCommon<unsigned int>();
+ nErrorCount += TestCmpCommon<unsigned short>();
+ nErrorCount += TestCmpCommon<unsigned long>();
+ nErrorCount += TestCmpCommon<unsigned long long>();
+
+ // Test integral comparison among different types
+ nErrorCount += TestUtilityCmpEql(int(0), short(0));
+ nErrorCount += TestUtilityCmpEql(short(2), long(2));
+ nErrorCount += TestUtilityCmpEql(short(3), unsigned long(3));
+ nErrorCount += TestUtilityCmpEql(int(-5), long long(-5));
+ nErrorCount += TestUtilityCmpEql(short(-100), long long(-100));
+ nErrorCount += TestUtilityCmpEql(unsigned int(100), long(100));
+ nErrorCount += TestUtilityCmpEql(unsigned long long(100), int(100));
+
+ nErrorCount += TestUtilityCmpLess(int(0), long long(1));
+ nErrorCount += TestUtilityCmpLess(int(-1), unsigned long(1));
+ nErrorCount += TestUtilityCmpLess(short(-100), long long(100));
+ nErrorCount += TestUtilityCmpLess(eastl::numeric_limits<long>::min(), short(0));
+ nErrorCount += TestUtilityCmpLess(short(0), eastl::numeric_limits<int>::max());
+ nErrorCount += TestUtilityCmpLess(eastl::numeric_limits<unsigned short>::min(), eastl::numeric_limits<int>::max());
+ nErrorCount += TestUtilityCmpLess(eastl::numeric_limits<short>::max(), eastl::numeric_limits<long>::max());
+ nErrorCount += TestUtilityCmpLess(eastl::numeric_limits<int>::max(), eastl::numeric_limits<long long>::max());
+ nErrorCount += TestUtilityCmpLess(int(-100), unsigned int(0));
+ nErrorCount += TestUtilityCmpLess(eastl::numeric_limits<int>::min(), eastl::numeric_limits<unsigned int>::min());
+
+ nErrorCount += TestUtilityCmpGreater(int(1), short(0));
+ nErrorCount += TestUtilityCmpGreater(unsigned long(1), int(-1));
+ nErrorCount += TestUtilityCmpGreater(unsigned long long(100), short(-100));
+ nErrorCount += TestUtilityCmpGreater(short(0), eastl::numeric_limits<short>::min());
+ nErrorCount += TestUtilityCmpGreater(eastl::numeric_limits<long>::max(), unsigned short(5));
+ nErrorCount += TestUtilityCmpGreater(eastl::numeric_limits<long>::max(), eastl::numeric_limits<int>::min());
+ nErrorCount += TestUtilityCmpGreater(eastl::numeric_limits<int>::max(), eastl::numeric_limits<short>::max());
+ nErrorCount += TestUtilityCmpGreater(eastl::numeric_limits<long long>::max(), eastl::numeric_limits<int>::max());
+ nErrorCount += TestUtilityCmpGreater(unsigned int(0), int(-100));
+ nErrorCount += TestUtilityCmpGreater(eastl::numeric_limits<unsigned int>::min(), eastl::numeric_limits<int>::min());
+
+ nErrorCount += TestUtilityCmpLessEq(int(0), short(1));
+ nErrorCount += TestUtilityCmpLessEq(int(-1), long long(-1));
+ nErrorCount += TestUtilityCmpLessEq(short(-100), unsigned long long(100));
+ nErrorCount += TestUtilityCmpLessEq(short(-100), long long(-100));
+ nErrorCount += TestUtilityCmpLessEq(eastl::numeric_limits<int>::min(), short(0));
+ nErrorCount += TestUtilityCmpLessEq(short(0), eastl::numeric_limits<int>::max());
+ nErrorCount += TestUtilityCmpLessEq(eastl::numeric_limits<short>::min(), eastl::numeric_limits<short>::min());
+ nErrorCount += TestUtilityCmpLessEq(eastl::numeric_limits<int>::max(), eastl::numeric_limits<int>::max());
+ nErrorCount += TestUtilityCmpLessEq(eastl::numeric_limits<int>::max(), eastl::numeric_limits<long long>::max());
+ nErrorCount += TestUtilityCmpLessEq(int(50), unsigned int(50));
+ nErrorCount += TestUtilityCmpLessEq(eastl::numeric_limits<int>::min(), eastl::numeric_limits<unsigned int>::min());
+
+ nErrorCount += TestUtilityCmpGreaterEq(int(1), short(1));
+ nErrorCount += TestUtilityCmpGreaterEq(long long(-1), int(-1));
+ nErrorCount += TestUtilityCmpGreaterEq(long long(-100), short(-100));
+ nErrorCount += TestUtilityCmpGreaterEq(short(0), long(0));
+ nErrorCount += TestUtilityCmpGreaterEq(eastl::numeric_limits<long>::max(), eastl::numeric_limits<long>::max());
+ nErrorCount += TestUtilityCmpGreaterEq(eastl::numeric_limits<int>::max(), eastl::numeric_limits<short>::min());
+ nErrorCount += TestUtilityCmpGreaterEq(eastl::numeric_limits<int>::max(), eastl::numeric_limits<short>::max());
+ nErrorCount += TestUtilityCmpGreaterEq(eastl::numeric_limits<long long>::max(), eastl::numeric_limits<int>::max());
+ nErrorCount += TestUtilityCmpGreaterEq(unsigned int(0), int(0));
+ nErrorCount += TestUtilityCmpGreaterEq(eastl::numeric_limits<unsigned int>::min(), eastl::numeric_limits<int>::min());
+
+ // Test in_range
+ EATEST_VERIFY(eastl::in_range<int>(0));
+ EATEST_VERIFY(eastl::in_range<int>(eastl::numeric_limits<int>::min()));
+ EATEST_VERIFY(eastl::in_range<int>(eastl::numeric_limits<int>::max()));
+ EATEST_VERIFY(eastl::in_range<unsigned int>(0));
+ EATEST_VERIFY(eastl::in_range<unsigned int>(eastl::numeric_limits<unsigned int>::min()));
+ EATEST_VERIFY(eastl::in_range<unsigned int>(eastl::numeric_limits<unsigned int>::max()));
+ EATEST_VERIFY(!eastl::in_range<unsigned int>(-1));
+ EATEST_VERIFY(!eastl::in_range<int>(eastl::numeric_limits<unsigned int>::max()));
+ EATEST_VERIFY(!eastl::in_range<unsigned int>(eastl::numeric_limits<int>::min()));
+
+ EATEST_VERIFY(eastl::in_range<short>(100));
+ EATEST_VERIFY(eastl::in_range<short>(eastl::numeric_limits<short>::min()));
+ EATEST_VERIFY(eastl::in_range<short>(eastl::numeric_limits<short>::max()));
+ EATEST_VERIFY(eastl::in_range<unsigned short>(100));
+ EATEST_VERIFY(eastl::in_range<unsigned short>(eastl::numeric_limits<unsigned short>::min()));
+ EATEST_VERIFY(eastl::in_range<unsigned short>(eastl::numeric_limits<unsigned short>::max()));
+ EATEST_VERIFY(!eastl::in_range<unsigned short>(-1));
+ EATEST_VERIFY(!eastl::in_range<short>(eastl::numeric_limits<unsigned int>::max()));
+ EATEST_VERIFY(!eastl::in_range<unsigned short>(eastl::numeric_limits<int>::min()));
+
+ EATEST_VERIFY(eastl::in_range<long>(50));
+ EATEST_VERIFY(eastl::in_range<long>(eastl::numeric_limits<long>::min()));
+ EATEST_VERIFY(eastl::in_range<long>(eastl::numeric_limits<long>::max()));
+ EATEST_VERIFY(eastl::in_range<unsigned long>(50));
+ EATEST_VERIFY(eastl::in_range<unsigned long>(eastl::numeric_limits<unsigned long>::min()));
+ EATEST_VERIFY(eastl::in_range<unsigned long>(eastl::numeric_limits<unsigned long>::max()));
+ EATEST_VERIFY(!eastl::in_range<unsigned long>(-1));
+ EATEST_VERIFY(!eastl::in_range<long>(eastl::numeric_limits<unsigned int>::max()));
+ EATEST_VERIFY(!eastl::in_range<unsigned long>(eastl::numeric_limits<int>::min()));
+
+ return nErrorCount;
+}
+#endif
+
///////////////////////////////////////////////////////////////////////////////
// TestUtility
//
@@ -627,6 +908,8 @@ int TestUtility()
nErrorCount += TestUtilityMove();
nErrorCount += TestUtilityIntegerSequence();
nErrorCount += TestUtilityExchange();
-
+#if defined(EA_COMPILER_CPP20_ENABLED)
+ nErrorCount += TestUtilityIntegralComp();
+#endif
return nErrorCount;
}
diff --git a/EASTL/test/source/TestVariant.cpp b/EASTL/test/source/TestVariant.cpp
index 8c71eda..2a78a89 100644
--- a/EASTL/test/source/TestVariant.cpp
+++ b/EASTL/test/source/TestVariant.cpp
@@ -7,12 +7,34 @@
#include <EASTL/string.h>
#include <EASTL/algorithm.h>
#include <EASTL/sort.h>
+#include <EASTL/bonus/overloaded.h>
#ifdef EA_COMPILER_CPP14_ENABLED
#include "ConceptImpls.h"
#include <EASTL/variant.h>
+#if EASTL_EXCEPTIONS_ENABLED
+
+// Intentionally Non-Trivial.
+// There are optimizations we can make in variant if the types are trivial that we don't currently do but can do.
+template <typename T>
+struct valueless_struct
+{
+ valueless_struct() {}
+
+ valueless_struct(const valueless_struct&) {}
+
+ ~valueless_struct() {}
+
+ struct exception_tag {};
+
+ operator T() const { throw exception_tag{}; }
+};
+
+#endif
+
+
int TestVariantAlternative()
{
using namespace eastl;
@@ -270,7 +292,7 @@ int TestVariantHoldsAlternative()
VERIFY(!holds_alternative<long>(v)); // Verify that a query for a T not in the variant typelist returns false.
VERIFY(!holds_alternative<string>(v)); // Verify that a query for a T not in the variant typelist returns false.
- VERIFY(!holds_alternative<int>(v)); // variant does not hold an int
+ VERIFY(!holds_alternative<int>(v)); // variant does not hold an int
VERIFY(!holds_alternative<short>(v)); // variant does not hold a short
}
@@ -356,7 +378,7 @@ int TestVariantValuelessByException()
VERIFY(!v.valueless_by_exception());
}
- // TODO(rparolin): review exception safety for variant types
+ // TODO(rparolin): review exception safety for variant types
//
// {
// #if EASTL_EXCEPTIONS_ENABLED
@@ -542,12 +564,12 @@ int TestVariantSwap()
v1.swap(v2);
- VERIFY(get<int>(v1) == 24);
+ VERIFY(get<int>(v1) == 24);
VERIFY(get<int>(v2) == 42);
v1.swap(v2);
- VERIFY(get<int>(v1) == 42);
+ VERIFY(get<int>(v1) == 42);
VERIFY(get<int>(v2) == 24);
}
@@ -555,13 +577,13 @@ int TestVariantSwap()
variant<string> v1 = "Hello";
variant<string> v2 = "World";
- VERIFY(get<string>(v1) == "Hello");
+ VERIFY(get<string>(v1) == "Hello");
VERIFY(get<string>(v2) == "World");
v1.swap(v2);
VERIFY(get<string>(v1) == "World");
- VERIFY(get<string>(v2) == "Hello");
+ VERIFY(get<string>(v2) == "Hello");
}
return nErrorCount;
@@ -625,32 +647,178 @@ int TestVariantInplaceCtors()
return nErrorCount;
}
+// Many Compilers are smart and will fully inline the visitor in our unittests,
+// Thereby not actually testing the recursive call.
+EA_NO_INLINE int TestVariantVisitNoInline(const eastl::variant<int, bool, unsigned>& v)
+{
+ int nErrorCount = 0;
+
+ bool bVisited = false;
-int TestVariantVisitor()
+ struct MyVisitor
+ {
+ MyVisitor() = delete;
+ MyVisitor(bool& visited) : mVisited(visited) {};
+
+ void operator()(int) { mVisited = true; }
+ void operator()(bool) { mVisited = true; }
+ void operator()(unsigned) { mVisited = true; }
+
+ bool& mVisited;
+ };
+
+ eastl::visit(MyVisitor(bVisited), v);
+
+ EATEST_VERIFY(bVisited);
+
+ return nErrorCount;
+}
+
+EA_NO_INLINE int TestVariantVisit2NoInline(const eastl::variant<int, bool>& v0, const eastl::variant<int, bool>& v1)
+{
+ int nErrorCount = 0;
+
+ bool bVisited = false;
+
+ struct MyVisitor
+ {
+ MyVisitor() = delete;
+ MyVisitor(bool& visited) : mVisited(visited) {};
+
+ void operator()(int, int) { mVisited = true; }
+ void operator()(bool, int) { mVisited = true; }
+ void operator()(int, bool) { mVisited = true; }
+ void operator()(bool, bool) { mVisited = true; }
+
+ bool& mVisited;
+ };
+
+ eastl::visit(MyVisitor(bVisited), v0, v1);
+
+ EATEST_VERIFY(bVisited);
+
+ return nErrorCount;
+}
+
+EA_NO_INLINE int TestVariantVisit3tNoInline(const eastl::variant<int, bool>& v0, const eastl::variant<int, bool>& v1, const eastl::variant<int, bool>& v2)
+{
+ int nErrorCount = 0;
+
+ bool bVisited = false;
+
+ struct MyVisitor
+ {
+ MyVisitor() = delete;
+ MyVisitor(bool& visited) : mVisited(visited) {};
+
+ void operator()(int, int, int) { mVisited = true; }
+ void operator()(bool, int, int) { mVisited = true; }
+ void operator()(int, bool, int) { mVisited = true; }
+ void operator()(bool, bool, int) { mVisited = true; }
+
+ void operator()(int, int, bool) { mVisited = true; }
+ void operator()(bool, int, bool) { mVisited = true; }
+ void operator()(int, bool, bool) { mVisited = true; }
+ void operator()(bool, bool, bool) { mVisited = true; }
+
+ bool& mVisited;
+ };
+
+ eastl::visit(MyVisitor(bVisited), v0, v1, v2);
+
+ EATEST_VERIFY(bVisited);
+
+ return nErrorCount;
+}
+
+int TestVariantVisitorOverloaded()
{
using namespace eastl;
int nErrorCount = 0;
using v_t = variant<int, string, double, long>;
+ v_t arr[] = {42, "jean", 42.0, 42L};
+ v_t v{42.0};
+
+
+ #ifdef __cpp_deduction_guides
+ {
+ int count = 0;
+
+ for (auto& e : arr)
+ {
+ eastl::visit(
+ overloaded{
+ [&](int) { count++; },
+ [&](string) { count++; },
+ [&](double) { count++; },
+ [&](long) { count++; }},
+ e
+ );
+ }
- // TODO(rparolin): When we have a C++17 compiler
- //
- // template deduction guides test
- // template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
- // template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
+ VERIFY(count == EAArrayCount(arr));
+ }
- // {
- // v_t arr[] = {42, "rob", 42.0, 42L};
+ {
+ double visitedValue = 0.0f;
+
+ eastl::visit(
+ overloaded{
+ [](int) { },
+ [](string) { },
+ [&](double d) { visitedValue = d; },
+ [](long) { }},
+ v
+ );
+
+ VERIFY(visitedValue == 42.0f);
+ }
- // int count = 0;
- // for (auto& e : arr)
- // {
- // eastl::visit(overloaded{[&](int) { count++; },
- // [&](string) { count++; },
- // [&](double) { count++; },
- // [&](long) { count++; }}, e);
- // }
- // }
+ #endif
+
+ {
+ int count = 0;
+
+ for (auto& e : arr)
+ {
+ eastl::visit(
+ eastl::make_overloaded(
+ [&](int) { count++; },
+ [&](string) { count++; },
+ [&](double) { count++; },
+ [&](long) { count++; }),
+ e
+ );
+ }
+
+ VERIFY(count == EAArrayCount(arr));
+ }
+
+ {
+ double visitedValue = 0.0f;
+
+ eastl::visit(
+ eastl::make_overloaded(
+ [](int) { },
+ [](string) { },
+ [&](double d) { visitedValue = d; },
+ [](long) { }),
+ v
+ );
+
+ VERIFY(visitedValue == 42.0f);
+ }
+
+ return nErrorCount;
+}
+
+int TestVariantVisitor()
+{
+ using namespace eastl;
+ int nErrorCount = 0;
+
+ using v_t = variant<int, string, double, long>;
{
v_t arr[] = {42, "hello", 42.0, 42L};
@@ -662,6 +830,14 @@ int TestVariantVisitor()
}
VERIFY(count == EAArrayCount(arr));
+
+ count = 0;
+ for (auto& e : arr)
+ {
+ eastl::visit<void>([&](auto){ count++; }, e);
+ }
+
+ VERIFY(count == EAArrayCount(arr));
}
{
@@ -671,14 +847,171 @@ int TestVariantVisitor()
struct MyVisitor
{
- MyVisitor& operator()(int) { bVisited = true; return *this; };
- MyVisitor& operator()(long) { return *this; };
- MyVisitor& operator()(string) { return *this; };
- MyVisitor& operator()(unsigned) { return *this; }; // not in variant
+ void operator()(int) { bVisited = true; };
+ void operator()(long) { };
+ void operator()(string) { };
+ void operator()(unsigned) { }; // not in variant
};
visit(MyVisitor{}, v);
VERIFY(bVisited);
+
+ bVisited = false;
+
+ visit<void>(MyVisitor{}, v);
+ VERIFY(bVisited);
+ }
+
+ {
+ static bool bVisited = false;
+
+ variant<int, bool, unsigned> v = (int)1;
+
+ struct MyVisitor
+ {
+ bool& operator()(int) { return bVisited; }
+ bool& operator()(bool) { return bVisited; }
+ bool& operator()(unsigned) { return bVisited; }
+ };
+
+ bool& ret = visit(MyVisitor{}, v);
+ ret = true;
+ VERIFY(bVisited);
+
+ bVisited = false;
+ bool& ret2 = visit<bool&>(MyVisitor{}, v);
+ ret2 = true;
+ VERIFY(bVisited);
+ }
+
+ {
+ variant<int, bool, unsigned> v = (int)1;
+
+ struct MyVisitor
+ {
+ void operator()(int& i) { i = 2; }
+ void operator()(bool&) {}
+ void operator()(unsigned&) {}
+ };
+
+ visit(MyVisitor{}, v);
+ EATEST_VERIFY(get<0>(v) == (int)2);
+
+ v = (int)1;
+ visit<void>(MyVisitor{}, v);
+ EATEST_VERIFY(get<0>(v) == (int)2);
+ }
+
+ {
+ static bool bVisited = false;
+
+ variant<int, bool, unsigned> v =(int)1;
+
+ struct MyVisitor
+ {
+ void operator()(const int&) { bVisited = true; }
+ void operator()(const bool&) {}
+ void operator()(const unsigned&) {}
+ };
+
+ visit(MyVisitor{}, v);
+ EATEST_VERIFY(bVisited);
+
+ bVisited = false;
+ visit<void>(MyVisitor{}, v);
+ EATEST_VERIFY(bVisited);
+ }
+
+ {
+ static bool bVisited = false;
+
+ const variant<int, bool, unsigned> v =(int)1;
+
+ struct MyVisitor
+ {
+ void operator()(const int&) { bVisited = true; }
+ void operator()(const bool&) {}
+ void operator()(const unsigned&) {}
+ };
+
+ visit(MyVisitor{}, v);
+ EATEST_VERIFY(bVisited);
+
+ bVisited = false;
+ visit<void>(MyVisitor{}, v);
+ EATEST_VERIFY(bVisited);
+ }
+
+ {
+ static bool bVisited = false;
+
+ struct MyVisitor
+ {
+ void operator()(int&&) { bVisited = true; }
+ void operator()(bool&&) {}
+ void operator()(unsigned&&) {}
+ };
+
+ visit(MyVisitor{}, variant<int, bool, unsigned>{(int)1});
+ EATEST_VERIFY(bVisited);
+
+ visit<void>(MyVisitor{}, variant<int, bool, unsigned>{(int)1});
+ EATEST_VERIFY(bVisited);
+ }
+
+ {
+ static bool bVisited = false;
+
+ variant<int, bool, unsigned> v = (int)1;
+
+ struct MyVisitor
+ {
+ bool&& operator()(int) { return eastl::move(bVisited); }
+ bool&& operator()(bool) { return eastl::move(bVisited); }
+ bool&& operator()(unsigned) { return eastl::move(bVisited); }
+ };
+
+ bool&& ret = visit(MyVisitor{}, v);
+ ret = true;
+ VERIFY(bVisited);
+
+ bVisited = false;
+ bool&& ret2 = visit<bool&&>(MyVisitor{}, v);
+ ret2 = true;
+ VERIFY(bVisited);
+ }
+
+ {
+ variant<int, bool, unsigned> v = (int)1;
+
+ TestVariantVisitNoInline(v);
+ v = (bool)true;
+ TestVariantVisitNoInline(v);
+ v = (int)3;
+ TestVariantVisitNoInline(v);
+ }
+
+ {
+ variant<int, bool> v0 = (int)1;
+ variant<int, bool> v1 = (bool)true;
+
+ TestVariantVisit2NoInline(v0, v1);
+ v0 = (bool)false;
+ TestVariantVisit2NoInline(v0, v1);
+ v1 = (int)2;
+ TestVariantVisit2NoInline(v0, v1);
+ }
+
+ {
+ variant<int, bool> v0 = (int)1;
+ variant<int, bool> v1 = (int)2;
+ variant<int, bool> v2 = (int)3;
+
+ TestVariantVisit3tNoInline(v0, v1, v2);
+ v2 = (bool)false;
+ TestVariantVisit3tNoInline(v0, v1, v2);
+ v0 = (bool)true;
+ TestVariantVisit3tNoInline(v0, v1, v2);
}
{
@@ -695,11 +1028,43 @@ int TestVariantVisitor()
MultipleVisitor& operator()(string, string) { return *this; }
};
- visit(MultipleVisitor{}, i, s);
+ MultipleVisitor& ret = visit(MultipleVisitor{}, i, s);
+ EA_UNUSED(ret);
+ VERIFY(bVisited);
+
+ MultipleVisitor& ret2 = visit<MultipleVisitor&>(MultipleVisitor{}, i, s);
+ EA_UNUSED(ret2);
VERIFY(bVisited);
}
{
+ bool bVisited = false;
+
+ variant<int, bool> v0 = 0;
+ variant<int, bool> v1 = 1;
+
+ struct MultipleVisitor
+ {
+ MultipleVisitor() = delete;
+ MultipleVisitor(bool& visited) : mVisited(visited) {};
+
+ void operator()(int, int) { mVisited = true; }
+ void operator()(int, bool) {}
+ void operator()(bool, int) {}
+ void operator()(bool, bool) {}
+
+ bool& mVisited;
+ };
+
+ visit(MultipleVisitor(bVisited), v0, v1);
+ EATEST_VERIFY(bVisited);
+
+ bVisited = false;
+ visit<void>(MultipleVisitor(bVisited), v0, v1);
+ EATEST_VERIFY(bVisited);
+ }
+
+ {
variant<int, string> v = 42;
struct ModifyingVisitor
@@ -724,24 +1089,128 @@ int TestVariantVisitor()
VERIFY(visit(ReturningVisitor{}, v) == 42);
}
-#if !defined(EA_COMPILER_MSVC)
+ return nErrorCount;
+}
+
+int TestVariantVisitorReturn()
+{
+ int nErrorCount = 0;
+
+ {
+ static bool bVisited = false;
+
+ eastl::variant<int, bool> v = (int)1;
+
+ struct MyVisitor
+ {
+ bool operator()(int) { bVisited = true; return true; }
+ bool operator()(bool) { return false; }
+ };
+
+ eastl::visit<void>(MyVisitor{}, v);
+ EATEST_VERIFY(bVisited);
+ }
+
{
- variant<int, string> v = 42;
+ static bool bVisited = false;
- struct ReturningDifferentTypesVisitor
+ eastl::variant<int, bool> v = (int)1;
+
+ struct MyVisitor
{
- int operator()(int i) {return i;}
- size_t operator()(string s) {return s.size();}
+ bool operator()(int) { bVisited = true; return true; }
+ bool operator()(bool) { return false; }
};
- VERIFY(visit(ReturningDifferentTypesVisitor{}, v) == 42);
+ eastl::visit<const void>(MyVisitor{}, v);
+ EATEST_VERIFY(bVisited);
+ }
+
+ {
+ static bool bVisited = false;
+
+ eastl::variant<int, bool> v = (int)1;
+
+ struct MyVisitor
+ {
+ bool operator()(int) { bVisited = true; return true; }
+ bool operator()(bool) { return false; }
+ };
+
+ eastl::visit<volatile void>(MyVisitor{}, v);
+ EATEST_VERIFY(bVisited);
+ }
+
+ {
+ static bool bVisited = false;
+
+ eastl::variant<int, bool> v = (int)1;
+
+ struct MyVisitor
+ {
+ bool operator()(int) { bVisited = true; return true; }
+ bool operator()(bool) { return false; }
+ };
+
+ eastl::visit<const volatile void>(MyVisitor{}, v);
+ EATEST_VERIFY(bVisited);
+ }
+
+ {
+ static bool bVisited = false;
+
+ eastl::variant<int, bool> v = (int)1;
+
+ struct MyVisitor
+ {
+ bool operator()(int) { bVisited = true; return true; }
+ bool operator()(bool) { return false; }
+ };
+
+ int ret = eastl::visit<int>(MyVisitor{}, v);
+ EATEST_VERIFY(bVisited);
+ EATEST_VERIFY(ret);
+ }
+
+ {
+ static bool bVisited = false;
+
+ struct A {};
+ struct B : public A {};
+ struct C : public A {};
+
+ eastl::variant<int, bool> v = (int)1;
+
+ struct MyVisitor
+ {
+ B operator()(int) { bVisited = true; return B{}; }
+ C operator()(bool) { return C{}; }
+ };
+
+ A ret = eastl::visit<A>(MyVisitor{}, v);
+ EA_UNUSED(ret);
+ EATEST_VERIFY(bVisited);
+ }
+
+ {
+ static bool bVisited = false;
+
+ eastl::variant<int, bool> v = (int)1;
+
+ struct MyVisitor
+ {
+ MyVisitor operator()(int) { bVisited = true; return MyVisitor{}; }
+ MyVisitor operator()(bool) { return MyVisitor{}; }
+ };
+
+ MyVisitor ret = eastl::visit<MyVisitor>(MyVisitor{}, v);
+ EA_UNUSED(ret);
+ EATEST_VERIFY(bVisited);
}
-#endif
return nErrorCount;
}
-
int TestVariantAssignment()
{
using namespace eastl;
@@ -825,6 +1294,328 @@ int TestVariantUserRegressionCopyMoveAssignmentOperatorLeak()
return nErrorCount;
}
+int TestVariantRelationalOperators()
+{
+ int nErrorCount = 0;
+
+ using VariantNoThrow = eastl::variant<int, bool, float>;
+
+ // Equality
+ {
+ {
+ VariantNoThrow v1{ (int)1 };
+ VariantNoThrow v2{ true };
+
+ EATEST_VERIFY((v1 == v2) == false);
+ }
+
+ {
+ VariantNoThrow v1{ (int)1 };
+ VariantNoThrow v2{ (int)1 };
+
+ EATEST_VERIFY((v1 == v2) == true);
+ }
+
+ {
+ VariantNoThrow v1{ (int)1 };
+ VariantNoThrow v2{ (int)0 };
+
+ EATEST_VERIFY((v1 == v2) == false);
+ }
+ }
+
+ // Inequality
+ {
+ {
+ VariantNoThrow v1{ (int)1 };
+ VariantNoThrow v2{ true };
+
+ EATEST_VERIFY((v1 != v2) == true);
+ }
+
+ {
+ VariantNoThrow v1{ (int)1 };
+ VariantNoThrow v2{ (int)1 };
+
+ EATEST_VERIFY((v1 != v2) == false);
+ }
+
+ {
+ VariantNoThrow v1{ (int)1 };
+ VariantNoThrow v2{ (int)0 };
+
+ EATEST_VERIFY((v1 != v2) == true);
+ }
+ }
+
+ // Less Than
+ {
+ {
+ VariantNoThrow v1{ (int)1 };
+ VariantNoThrow v2{ true };
+
+ EATEST_VERIFY((v1 < v2) == true);
+ }
+
+ {
+ VariantNoThrow v1{ true };
+ VariantNoThrow v2{ (int)1 };
+
+ EATEST_VERIFY((v1 < v2) == false);
+ }
+
+ {
+ VariantNoThrow v1{ (int)1 };
+ VariantNoThrow v2{ (int)1 };
+
+ EATEST_VERIFY((v1 < v2) == false);
+ }
+
+ {
+ VariantNoThrow v1{ (int)0 };
+ VariantNoThrow v2{ (int)1 };
+
+ EATEST_VERIFY((v1 < v2) == true);
+ }
+ }
+
+ // Greater Than
+ {
+ {
+ VariantNoThrow v1{ (int)1 };
+ VariantNoThrow v2{ true };
+
+ EATEST_VERIFY((v1 > v2) == false);
+ }
+
+ {
+ VariantNoThrow v1{ true };
+ VariantNoThrow v2{ (int)1 };
+
+ EATEST_VERIFY((v1 > v2) == true);
+ }
+
+ {
+ VariantNoThrow v1{ (int)1 };
+ VariantNoThrow v2{ (int)1 };
+
+ EATEST_VERIFY((v1 > v2) == false);
+ }
+
+ {
+ VariantNoThrow v1{ (int)1 };
+ VariantNoThrow v2{ (int)0 };
+
+ EATEST_VERIFY((v1 > v2) == true);
+ }
+ }
+
+ // Less Equal
+ {
+ {
+ VariantNoThrow v1{ (int)1 };
+ VariantNoThrow v2{ true };
+
+ EATEST_VERIFY((v1 <= v2) == true);
+ }
+
+ {
+ VariantNoThrow v1{ true };
+ VariantNoThrow v2{ (int)1 };
+
+ EATEST_VERIFY((v1 <= v2) == false);
+ }
+
+ {
+ VariantNoThrow v1{ (int)1 };
+ VariantNoThrow v2{ (int)1 };
+
+ EATEST_VERIFY((v1 <= v2) == true);
+ }
+
+ {
+ VariantNoThrow v1{ (int)0 };
+ VariantNoThrow v2{ (int)1 };
+
+ EATEST_VERIFY((v1 <= v2) == true);
+ }
+
+ {
+ VariantNoThrow v1{ (int)1 };
+ VariantNoThrow v2{ (int)0 };
+
+ EATEST_VERIFY((v1 <= v2) == false);
+ }
+ }
+
+ // Greater Equal
+ {
+ {
+ VariantNoThrow v1{ (int)1 };
+ VariantNoThrow v2{ true };
+
+ EATEST_VERIFY((v1 >= v2) == false);
+ }
+
+ {
+ VariantNoThrow v1{ true };
+ VariantNoThrow v2{ (int)1 };
+
+ EATEST_VERIFY((v1 >= v2) == true);
+ }
+
+ {
+ VariantNoThrow v1{ (int)1 };
+ VariantNoThrow v2{ (int)1 };
+
+ EATEST_VERIFY((v1 >= v2) == true);
+ }
+
+ {
+ VariantNoThrow v1{ (int)0 };
+ VariantNoThrow v2{ (int)1 };
+
+ EATEST_VERIFY((v1 >= v2) == false);
+ }
+
+ {
+ VariantNoThrow v1{ (int)1 };
+ VariantNoThrow v2{ (int)0 };
+
+ EATEST_VERIFY((v1 >= v2) == true);
+ }
+ }
+
+#if EASTL_EXCEPTIONS_ENABLED
+
+ using VariantThrow = eastl::variant<int, bool, float>;
+
+ auto make_variant_valueless = [](VariantThrow& v)
+ {
+ try
+ {
+ v.emplace<0>(valueless_struct<int>{});
+ }
+ catch(const typename valueless_struct<int>::exception_tag &)
+ {
+ }
+ };
+
+ // Equality
+ {
+ {
+ VariantThrow v0{ (int)0 };
+ VariantThrow v1{ (int)1 };
+
+ make_variant_valueless(v0);
+ make_variant_valueless(v1);
+
+ EATEST_VERIFY((v0 == v1) == true);
+ }
+ }
+
+ // Inequality
+ {
+ {
+ VariantThrow v0{ (int)0 };
+ VariantThrow v1{ (int)1 };
+
+ make_variant_valueless(v0);
+ make_variant_valueless(v1);
+
+ EATEST_VERIFY((v0 != v1) == false);
+ }
+ }
+
+ // Less Than
+ {
+ {
+ VariantThrow v0{ (int)0 };
+ VariantThrow v1{ (int)1 };
+
+ make_variant_valueless(v0);
+
+ EATEST_VERIFY((v0 < v1) == true);
+ }
+
+ {
+ VariantThrow v0{ (int)0 };
+ VariantThrow v1{ (int)1 };
+
+ make_variant_valueless(v1);
+
+ EATEST_VERIFY((v0 < v1) == false);
+ }
+ }
+
+ // Greater Than
+ {
+ {
+ VariantThrow v0{ (int)1 };
+ VariantThrow v1{ (int)0 };
+
+ make_variant_valueless(v0);
+
+ EATEST_VERIFY((v0 > v1) == false);
+ }
+
+ {
+ VariantThrow v0{ (int)1 };
+ VariantThrow v1{ (int)0 };
+
+ make_variant_valueless(v1);
+
+ EATEST_VERIFY((v0 > v1) == true);
+ }
+ }
+
+ // Less Equal
+ {
+ {
+ VariantThrow v0{ (int)1 };
+ VariantThrow v1{ (int)1 };
+
+ make_variant_valueless(v0);
+
+ EATEST_VERIFY((v0 <= v1) == true);
+ }
+
+ {
+ VariantThrow v0{ (int)1 };
+ VariantThrow v1{ (int)0 };
+
+ make_variant_valueless(v1);
+
+ EATEST_VERIFY((v0 <= v1) == false);
+ }
+ }
+
+ // Greater Equal
+ {
+ {
+ VariantThrow v0{ (int)1 };
+ VariantThrow v1{ (int)1 };
+
+ make_variant_valueless(v0);
+
+ EATEST_VERIFY((v0 >= v1) == false);
+ }
+
+ {
+ VariantThrow v0{ (int)1 };
+ VariantThrow v1{ (int)0 };
+
+ make_variant_valueless(v1);
+
+ EATEST_VERIFY((v0 >= v1) == true);
+ }
+ }
+
+#endif
+
+ return nErrorCount;
+}
+
int TestVariantUserRegressionIncompleteType()
{
@@ -848,6 +1639,155 @@ int TestVariantUserRegressionIncompleteType()
return nErrorCount;
}
+#define EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(Type, VarName) \
+ bool operator==(const Type & rhs) const { return VarName == rhs.VarName; } \
+ bool operator!=(const Type & rhs) const { return VarName != rhs.VarName; } \
+ bool operator<(const Type & rhs) const { return VarName < rhs.VarName; } \
+ bool operator>(const Type & rhs) const { return VarName > rhs.VarName; } \
+ bool operator<=(const Type & rhs) const { return VarName <= rhs.VarName; } \
+ bool operator>=(const Type & rhs) const { return VarName >= rhs.VarName; }
+
+int TestBigVariantComparison()
+{
+ int nErrorCount = 0;
+
+ struct A;
+ struct B;
+ struct C;
+ struct D;
+ struct E;
+ struct F;
+ struct G;
+ struct H;
+ struct I;
+ struct J;
+ struct K;
+ struct L;
+ struct M;
+ struct N;
+ struct O;
+ struct P;
+ struct Q;
+ struct R;
+ struct S;
+ struct T;
+ struct U;
+ struct V;
+ struct W;
+ struct X;
+ struct Y;
+ struct Z;
+
+ using BigVariant = eastl::variant<A, B, C, D, E, F, G, H, I, J, K, L, M, N,
+ O, P, Q, R, S, T, U, V, W, X, Y, Z>;
+
+ struct A { int a; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(A, a) };
+ struct B { int b; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(B, b) };
+ struct C { int c; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(C, c) };
+ struct D { int d; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(D, d) };
+ struct E { int e; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(E, e) };
+ struct F { int f; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(F, f) };
+ struct G { int g; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(G, g) };
+ struct H { int h; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(H, h) };
+ struct I { int i; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(I, i) };
+ struct J { int j; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(J, j) };
+ struct K { int k; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(K, k) };
+ struct L { int l; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(L, l) };
+ struct M { int m; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(M, m) };
+ struct N { int n; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(N, n) };
+ struct O { int o; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(O, o) };
+ struct P { int p; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(P, p) };
+ struct Q { int q; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(Q, q) };
+ struct R { int r; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(R, r) };
+ struct S { int s; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(S, s) };
+ struct T { int t; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(T, t) };
+ struct U { int u; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(U, u) };
+ struct V { int v; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(V, v) };
+ struct W { int w; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(W, w) };
+ struct X { int x; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(X, x) };
+ struct Y { int y; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(Y, y) };
+ struct Z { int z; EASTL_TEST_BIG_VARIANT_RELATIONAL_OPS(Z, z) };
+
+ {
+ BigVariant v0{ A{0} };
+ BigVariant v1{ A{1} };
+
+ VERIFY(v0 != v1);
+ }
+
+ {
+ BigVariant v0{ A{0} };
+ BigVariant v1{ A{1} };
+
+ VERIFY(v0 < v1);
+ }
+
+ {
+ BigVariant v0{ A{0} };
+ BigVariant v1{ A{0} };
+
+ VERIFY(v0 == v1);
+ }
+
+ {
+ BigVariant v0{ A{1} };
+ BigVariant v1{ A{0} };
+
+ VERIFY(v0 > v1);
+ }
+
+ {
+ BigVariant v0{ A{0} };
+ BigVariant v1{ A{1} };
+
+ VERIFY(v0 <= v1);
+ }
+
+ {
+ BigVariant v0{ A{0} };
+ BigVariant v1{ A{0} };
+
+ VERIFY(v0 <= v1);
+ }
+
+ {
+ BigVariant v0{ A{0} };
+ BigVariant v1{ A{0} };
+
+ VERIFY(v0 >= v1);
+ }
+
+ {
+ BigVariant v0{ A{1} };
+ BigVariant v1{ A{0} };
+
+ VERIFY(v0 >= v1);
+ }
+
+ {
+ BigVariant v0{ A{0} };
+ BigVariant v1{ B{0} };
+
+ VERIFY(v0 != v1);
+ }
+
+ {
+ BigVariant v0{ A{0} };
+ BigVariant v1{ B{0} };
+
+ VERIFY(v0 < v1);
+ }
+
+ {
+ BigVariant v0{ A{0} };
+ BigVariant v1{ B{0} };
+
+ VERIFY(v1 > v0);
+ }
+
+ return nErrorCount;
+}
+
int TestVariantGeneratingComparisonOverloads();
int TestVariant()
@@ -866,25 +1806,18 @@ int TestVariant()
nErrorCount += TestVariantEmplace();
nErrorCount += TestVariantRelOps();
nErrorCount += TestVariantInplaceCtors();
+ nErrorCount += TestVariantVisitorOverloaded();
nErrorCount += TestVariantVisitor();
nErrorCount += TestVariantAssignment();
nErrorCount += TestVariantMoveOnly();
nErrorCount += TestVariantUserRegressionCopyMoveAssignmentOperatorLeak();
nErrorCount += TestVariantUserRegressionIncompleteType();
nErrorCount += TestVariantGeneratingComparisonOverloads();
+ nErrorCount += TestBigVariantComparison();
+ nErrorCount += TestVariantRelationalOperators();
return nErrorCount;
}
#else
int TestVariant() { return 0; }
#endif
-
-
-
-
-
-
-
-
-
-
diff --git a/EASTL/test/source/TestVector.cpp b/EASTL/test/source/TestVector.cpp
index 0fe719d..69cdb52 100644
--- a/EASTL/test/source/TestVector.cpp
+++ b/EASTL/test/source/TestVector.cpp
@@ -1258,6 +1258,84 @@ int TestVector()
EATEST_VERIFY(!(intArray1 > intArray2));
}
+ // three way comparison operator
+#if defined(EA_COMPILER_HAS_THREE_WAY_COMPARISON)
+ {
+ using namespace eastl;
+
+ vector<int> intArray1(10);
+ vector<int> intArray2(10);
+
+ for (i = 0; i < intArray1.size(); i++)
+ {
+ intArray1[i] = (int)i; // Make intArray1 equal to intArray2.
+ intArray2[i] = (int)i;
+ }
+
+ // Verify equality between intArray1 and intArray2
+ EATEST_VERIFY((intArray1 <=> intArray2) == 0);
+ EATEST_VERIFY(!((intArray1 <=> intArray2) != 0));
+ EATEST_VERIFY((intArray1 <=> intArray2) <= 0);
+ EATEST_VERIFY((intArray1 <=> intArray2) >= 0);
+ EATEST_VERIFY(!((intArray1 <=> intArray2) < 0));
+ EATEST_VERIFY(!((intArray1 <=> intArray2) > 0));
+
+ intArray1.push_back(100); // Make intArray1 less than intArray2.
+ intArray2.push_back(101);
+
+ // Verify intArray1 < intArray2
+ EATEST_VERIFY(!((intArray1 <=> intArray2) == 0));
+ EATEST_VERIFY((intArray1 <=> intArray2) != 0);
+ EATEST_VERIFY((intArray1 <=> intArray2) <= 0);
+ EATEST_VERIFY(!((intArray1 <=> intArray2) >= 0));
+ EATEST_VERIFY(((intArray1 <=> intArray2) < 0));
+ EATEST_VERIFY(!((intArray1 <=> intArray2) > 0));
+
+ for (i = 0; i < 3; i++) // Make the length of intArray2 less than intArray1
+ intArray2.pop_back();
+
+ // Verify intArray2.size() < intArray1.size() and intArray2 is a subset of intArray1
+ EATEST_VERIFY(!((intArray1 <=> intArray2) == 0));
+ EATEST_VERIFY((intArray1 <=> intArray2) != 0);
+ EATEST_VERIFY((intArray1 <=> intArray2) >= 0);
+ EATEST_VERIFY(!((intArray1 <=> intArray2) <= 0));
+ EATEST_VERIFY(((intArray1 <=> intArray2) > 0));
+ EATEST_VERIFY(!((intArray1 <=> intArray2) < 0));
+ }
+
+ {
+ using namespace eastl;
+
+ vector<int> intArray1 = {1, 2, 3, 4, 5, 6, 7};
+ vector<int> intArray2 = {7, 6, 5, 4, 3, 2, 1};
+ vector<int> intArray3 = {1, 2, 3, 4};
+
+ struct weak_ordering_vector
+ {
+ vector<int> vec;
+ inline std::weak_ordering operator<=>(const weak_ordering_vector& b) const { return vec <=> b.vec; }
+ };
+
+ EATEST_VERIFY(synth_three_way{}(weak_ordering_vector{intArray1}, weak_ordering_vector{intArray2}) == std::weak_ordering::less);
+ EATEST_VERIFY(synth_three_way{}(weak_ordering_vector{intArray3}, weak_ordering_vector{intArray1}) == std::weak_ordering::less);
+ EATEST_VERIFY(synth_three_way{}(weak_ordering_vector{intArray2}, weak_ordering_vector{intArray1}) == std::weak_ordering::greater);
+ EATEST_VERIFY(synth_three_way{}(weak_ordering_vector{intArray2}, weak_ordering_vector{intArray3}) == std::weak_ordering::greater);
+ EATEST_VERIFY(synth_three_way{}(weak_ordering_vector{intArray1}, weak_ordering_vector{intArray1}) == std::weak_ordering::equivalent);
+
+ struct strong_ordering_vector
+ {
+ vector<int> vec;
+ inline std::strong_ordering operator<=>(const strong_ordering_vector& b) const { return vec <=> b.vec; }
+ };
+
+ EATEST_VERIFY(synth_three_way{}(strong_ordering_vector{intArray1}, strong_ordering_vector{intArray2}) == std::strong_ordering::less);
+ EATEST_VERIFY(synth_three_way{}(strong_ordering_vector{intArray3}, strong_ordering_vector{intArray1}) == std::strong_ordering::less);
+ EATEST_VERIFY(synth_three_way{}(strong_ordering_vector{intArray2}, strong_ordering_vector{intArray1}) == std::strong_ordering::greater);
+ EATEST_VERIFY(synth_three_way{}(strong_ordering_vector{intArray2}, strong_ordering_vector{intArray3}) == std::strong_ordering::greater);
+ EATEST_VERIFY(synth_three_way{}(strong_ordering_vector{intArray1}, strong_ordering_vector{intArray1}) == std::strong_ordering::equal);
+ }
+#endif
+
{
using namespace eastl;
@@ -1317,7 +1395,7 @@ int TestVector()
eastl::vector<TestObject> toTest;
// InputIterator
- demoted_iterator<TestObject*, eastl::forward_iterator_tag> toInput(&to);
+ demoted_iterator<TestObject*, EASTL_ITC_NS::forward_iterator_tag> toInput(&to);
toTest.assign(toInput, toInput);
// ForwardIterator
@@ -1637,7 +1715,7 @@ int TestVector()
{
struct iterator
{
- typedef eastl::input_iterator_tag iterator_category;
+ typedef EASTL_ITC_NS::input_iterator_tag iterator_category;
typedef int value_type;
typedef ptrdiff_t difference_type;
typedef int* pointer;
@@ -1718,20 +1796,24 @@ int TestVector()
{
eastl::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- eastl::erase(v, 5);
+ auto numErased = eastl::erase(v, 5);
VERIFY((v == eastl::vector<int> {1, 2, 3, 4, 6, 7, 8, 9}));
+ VERIFY(numErased == 1);
- eastl::erase(v, 2);
+ numErased = eastl::erase(v, 2);
VERIFY((v == eastl::vector<int> {1, 3, 4, 6, 7, 8, 9}));
+ VERIFY(numErased == 1);
- eastl::erase(v, 9);
+ numErased = eastl::erase(v, 9);
VERIFY((v == eastl::vector<int> {1, 3, 4, 6, 7, 8}));
+ VERIFY(numErased == 1);
}
{
eastl::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- eastl::erase_if(v, [](auto i) { return i % 2 == 0; });
+ auto numErased = eastl::erase_if(v, [](auto i) { return i % 2 == 0; });
VERIFY((v == eastl::vector<int>{1, 3, 5, 7, 9}));
+ VERIFY(numErased == 4);
}
}
diff --git a/EASTL/test/source/main.cpp b/EASTL/test/source/main.cpp
index 962d2c4..132bab1 100644
--- a/EASTL/test/source/main.cpp
+++ b/EASTL/test/source/main.cpp
@@ -145,6 +145,7 @@ int EAMain(int argc, char* argv[])
testSuite.AddTest("VectorSet", TestVectorSet);
testSuite.AddTest("AtomicBasic", TestAtomicBasic);
testSuite.AddTest("AtomicAsm", TestAtomicAsm);
+ testSuite.AddTest("Bitcast", TestBitcast);
nErrorCount += testSuite.Run();