mirror of
https://github.com/grumpycoders/pcsx-redux.git
synced 2025-04-02 10:41:54 -04:00
1739 lines
56 KiB
C++
1739 lines
56 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Copyright (c) Electronic Arts Inc. All rights reserved.
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "EASTLTest.h"
|
|
#include <EASTL/vector.h>
|
|
#include <EASTL/string.h>
|
|
#include <EASTL/deque.h>
|
|
#include <EASTL/list.h>
|
|
#include <EASTL/slist.h>
|
|
#include <EASTL/algorithm.h>
|
|
#include <EASTL/utility.h>
|
|
#include <EASTL/allocator_malloc.h>
|
|
#include <EASTL/unique_ptr.h>
|
|
|
|
#include "ConceptImpls.h"
|
|
|
|
|
|
EA_DISABLE_ALL_VC_WARNINGS()
|
|
#ifndef EA_COMPILER_NO_STANDARD_CPP_LIBRARY
|
|
#include <vector>
|
|
#include <string>
|
|
#endif
|
|
EA_RESTORE_ALL_VC_WARNINGS()
|
|
|
|
|
|
// Template instantations.
|
|
// These tell the compiler to compile all the functions for the given class.
|
|
template class eastl::vector<bool>;
|
|
template class eastl::vector<int>;
|
|
template class eastl::vector<Align64>;
|
|
template class eastl::vector<TestObject>;
|
|
|
|
|
|
// This tests "uninitialized_fill" usage in vector when T has a user provided
|
|
// address-of operator overload. In these situations, EASTL containers must use
|
|
// the standard utility "eastl::addressof(T)" which is designed to by-pass user
|
|
// provided address-of operator overloads.
|
|
//
|
|
// Previously written as:
|
|
// for(; first != last; ++first, ++currentDest)
|
|
// ::new((void*)&*currentDest) value_type(*first); // & not guaranteed to be a pointer
|
|
//
|
|
// Bypasses user 'addressof' operators:
|
|
// for(; n > 0; --n, ++currentDest)
|
|
// ::new(eastl::addressof(*currentDest)) value_type(value); // guaranteed to be a pointer
|
|
//
|
|
struct AddressOfOperatorResult {};
|
|
struct HasAddressOfOperator
|
|
{
|
|
// problematic 'addressof' operator that doesn't return a pointer type
|
|
AddressOfOperatorResult operator&() const { return {}; }
|
|
bool operator==(const HasAddressOfOperator&) const { return false; }
|
|
};
|
|
template class eastl::vector<HasAddressOfOperator>; // force compile all functions of vector
|
|
|
|
|
|
|
|
// Test compiler issue that appeared in VS2012 relating to kAlignment
|
|
struct StructWithContainerOfStructs
|
|
{
|
|
eastl::vector<StructWithContainerOfStructs> children;
|
|
};
|
|
|
|
// This relatively complex test is to prevent a regression on VS2013. The data types have what may appear to be
|
|
// strange names (for test code) because the code is based on a test case extracted from the Frostbite codebase.
|
|
// This test is actually invalid and should be removed as const data memebers are problematic for STL container
|
|
// implementations. (ie. they prevent constructors from being generated).
|
|
namespace
|
|
{
|
|
EA_DISABLE_VC_WARNING(4512) // disable warning : "assignment operator could not be generated"
|
|
#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) // VS2015-preview and later.
|
|
EA_DISABLE_VC_WARNING(5025) // disable warning : "move assignment operator could not be generated"
|
|
EA_DISABLE_VC_WARNING(4626) // disable warning : "assignment operator was implicitly defined as deleted"
|
|
EA_DISABLE_VC_WARNING(5027) // disable warning : "move assignment operator was implicitly defined as deleted"
|
|
#endif
|
|
struct ScenarioRefEntry
|
|
{
|
|
ScenarioRefEntry(const eastl::string& contextDatabase) : ContextDatabase(contextDatabase) {}
|
|
|
|
struct RowEntry
|
|
{
|
|
RowEntry(int levelId, int sceneId, int actorId, int partId, const eastl::string& controller)
|
|
: LevelId(levelId), SceneId(sceneId), ActorId(actorId), PartId(partId), Controller(controller)
|
|
{
|
|
}
|
|
|
|
int LevelId;
|
|
int SceneId;
|
|
int ActorId;
|
|
int PartId;
|
|
const eastl::string& Controller;
|
|
};
|
|
const eastl::string& ContextDatabase; // note: const class members prohibits move semantics
|
|
typedef eastl::vector<RowEntry> RowData;
|
|
RowData Rows;
|
|
};
|
|
typedef eastl::vector<ScenarioRefEntry> ScenarRefData;
|
|
struct AntMetaDataRecord
|
|
{
|
|
ScenarRefData ScenarioRefs;
|
|
};
|
|
typedef eastl::vector<AntMetaDataRecord> MetadataRecords;
|
|
|
|
struct StructWithConstInt
|
|
{
|
|
StructWithConstInt(const int& _i) : i(_i) {}
|
|
const int i;
|
|
};
|
|
|
|
struct StructWithConstRefToInt
|
|
{
|
|
StructWithConstRefToInt(const int& _i) : i(_i) {}
|
|
const int& i;
|
|
};
|
|
#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) // VS2015-preview and later.
|
|
EA_RESTORE_VC_WARNING() // disable warning 5025: "move assignment operator could not be generated"
|
|
EA_RESTORE_VC_WARNING() // disable warning 4626: "assignment operator was implicitly defined as deleted"
|
|
EA_RESTORE_VC_WARNING() // disable warning 5027: "move assignment operator was implicitly defined as deleted"
|
|
#endif
|
|
EA_RESTORE_VC_WARNING()
|
|
}
|
|
|
|
struct ItemWithConst
|
|
{
|
|
ItemWithConst& operator=(const ItemWithConst&);
|
|
|
|
public:
|
|
ItemWithConst(int _i) : i(_i) {}
|
|
ItemWithConst(const ItemWithConst& x) : i(x.i) {}
|
|
const int i;
|
|
};
|
|
|
|
struct testmovable
|
|
{
|
|
EA_NON_COPYABLE(testmovable)
|
|
public:
|
|
testmovable() EA_NOEXCEPT {}
|
|
|
|
testmovable(testmovable&&) EA_NOEXCEPT {}
|
|
|
|
testmovable& operator=(testmovable&&) EA_NOEXCEPT { return *this; }
|
|
};
|
|
|
|
struct TestMoveAssignToSelf
|
|
{
|
|
TestMoveAssignToSelf() EA_NOEXCEPT : mMovedToSelf(false) {}
|
|
TestMoveAssignToSelf(const TestMoveAssignToSelf& other) { mMovedToSelf = other.mMovedToSelf; }
|
|
TestMoveAssignToSelf& operator=(TestMoveAssignToSelf&&) { mMovedToSelf = true; return *this; }
|
|
TestMoveAssignToSelf& operator=(const TestMoveAssignToSelf&) = delete;
|
|
|
|
bool mMovedToSelf;
|
|
};
|
|
|
|
#if EASTL_VARIABLE_TEMPLATES_ENABLED
|
|
/// custom type-trait which checks if a type is comparable via the <operator.
|
|
template <class, class = eastl::void_t<>>
|
|
struct is_less_comparable : eastl::false_type { };
|
|
template <class T>
|
|
struct is_less_comparable<T, eastl::void_t<decltype(eastl::declval<T>() < eastl::declval<T>())>> : eastl::true_type { };
|
|
#else
|
|
// bypass the test since the compiler doesn't support variable templates.
|
|
template <class> struct is_less_comparable : eastl::false_type { };
|
|
#endif
|
|
|
|
|
|
int TestVector()
|
|
{
|
|
int nErrorCount = 0;
|
|
eastl_size_t i;
|
|
|
|
TestObject::Reset();
|
|
|
|
{
|
|
MetadataRecords mMetadataRecords;
|
|
AntMetaDataRecord r, s;
|
|
mMetadataRecords.push_back(r);
|
|
mMetadataRecords.push_back(s);
|
|
}
|
|
|
|
{
|
|
using namespace eastl;
|
|
|
|
// explicit vector();
|
|
vector<int> intArray1;
|
|
vector<TestObject> toArray1;
|
|
vector<list<TestObject> > toListArray1;
|
|
|
|
EATEST_VERIFY(intArray1.validate());
|
|
EATEST_VERIFY(intArray1.empty());
|
|
EATEST_VERIFY(toArray1.validate());
|
|
EATEST_VERIFY(toArray1.empty());
|
|
EATEST_VERIFY(toListArray1.validate());
|
|
EATEST_VERIFY(toListArray1.empty());
|
|
|
|
// explicit vector(const allocator_type& allocator);
|
|
MallocAllocator::reset_all();
|
|
MallocAllocator ma;
|
|
vector<int, MallocAllocator> intArray6(ma);
|
|
vector<TestObject, MallocAllocator> toArray6(ma);
|
|
vector<list<TestObject>, MallocAllocator> toListArray6(ma);
|
|
intArray6.resize(1);
|
|
toArray6.resize(1);
|
|
toListArray6.resize(1);
|
|
EATEST_VERIFY(MallocAllocator::mAllocCountAll == 3);
|
|
|
|
// explicit vector(size_type n, const allocator_type& allocator = EASTL_VECTOR_DEFAULT_ALLOCATOR)
|
|
vector<int> intArray2(10);
|
|
vector<TestObject> toArray2(10);
|
|
vector<list<TestObject> > toListArray2(10);
|
|
|
|
EATEST_VERIFY(intArray2.validate());
|
|
EATEST_VERIFY(intArray2.size() == 10);
|
|
EATEST_VERIFY(toArray2.validate());
|
|
EATEST_VERIFY(toArray2.size() == 10);
|
|
EATEST_VERIFY(toListArray2.validate());
|
|
EATEST_VERIFY(toListArray2.size() == 10);
|
|
|
|
// vector(size_type n, const value_type& value, const allocator_type& allocator =
|
|
// EASTL_VECTOR_DEFAULT_ALLOCATOR)
|
|
vector<int> intArray3(10, 7);
|
|
vector<TestObject> toArray3(10, TestObject(7));
|
|
vector<list<TestObject> > toListArray3(10, list<TestObject>(7));
|
|
|
|
EATEST_VERIFY(intArray3.validate());
|
|
EATEST_VERIFY(intArray3.size() == 10);
|
|
EATEST_VERIFY(intArray3[5] == 7);
|
|
EATEST_VERIFY(toArray3.validate());
|
|
EATEST_VERIFY(toArray3[5] == TestObject(7));
|
|
EATEST_VERIFY(toListArray3.validate());
|
|
EATEST_VERIFY(toListArray3[5] == list<TestObject>(7));
|
|
|
|
// vector(const vector& x)
|
|
vector<int> intArray4(intArray2);
|
|
vector<TestObject> toArray4(toArray2);
|
|
vector<list<TestObject> > toListArray4(toListArray2);
|
|
|
|
EATEST_VERIFY(intArray4.validate());
|
|
EATEST_VERIFY(intArray4 == intArray2);
|
|
EATEST_VERIFY(toArray4.validate());
|
|
EATEST_VERIFY(toArray4 == toArray2);
|
|
EATEST_VERIFY(intArray4.validate());
|
|
EATEST_VERIFY(toListArray4 == toListArray2);
|
|
|
|
// vector(const this_type& x, const allocator_type& allocator)
|
|
MallocAllocator::reset_all();
|
|
vector<int, MallocAllocator> intArray7(intArray6, ma);
|
|
vector<TestObject, MallocAllocator> toArray7(toArray6, ma);
|
|
vector<list<TestObject>, MallocAllocator> toListArray7(toListArray6, ma);
|
|
EATEST_VERIFY(MallocAllocator::mAllocCountAll == 3);
|
|
|
|
// vector(InputIterator first, InputIterator last)
|
|
deque<int> intDeque(3);
|
|
deque<TestObject> toDeque(3);
|
|
deque<list<TestObject> > toListDeque(3);
|
|
|
|
vector<int> intArray5(intDeque.begin(), intDeque.end());
|
|
vector<TestObject> toArray5(toDeque.begin(), toDeque.end());
|
|
vector<list<TestObject> > toListArray5(toListDeque.begin(), toListDeque.end());
|
|
|
|
// vector(std::initializer_list<T> ilist, const Allocator& allocator = EASTL_VECTOR_DEFAULT_ALLOCATOR);
|
|
{
|
|
#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)
|
|
eastl::vector<float> floatVector{0, 1, 2, 3};
|
|
|
|
EATEST_VERIFY(floatVector.size() == 4);
|
|
EATEST_VERIFY((floatVector[0] == 0) && (floatVector[3] == 3));
|
|
#endif
|
|
}
|
|
|
|
// vector& operator=(const vector& x);
|
|
intArray3 = intArray4;
|
|
toArray3 = toArray4;
|
|
toListArray3 = toListArray4;
|
|
|
|
EATEST_VERIFY(intArray3.validate());
|
|
EATEST_VERIFY(intArray3 == intArray4);
|
|
EATEST_VERIFY(toArray3.validate());
|
|
EATEST_VERIFY(toArray3 == toArray4);
|
|
EATEST_VERIFY(intArray3.validate());
|
|
EATEST_VERIFY(toListArray3 == toListArray4);
|
|
|
|
// this_type& operator=(std::initializer_list<T> ilist);
|
|
#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)
|
|
intArray3 = {0, 1, 2, 3};
|
|
EATEST_VERIFY((intArray3.size() == 4) && (intArray3[0] == 0) && (intArray3[3] == 3));
|
|
#endif
|
|
}
|
|
|
|
EATEST_VERIFY(TestObject::IsClear());
|
|
TestObject::Reset();
|
|
|
|
{
|
|
using namespace eastl;
|
|
|
|
// vector(this_type&& x)
|
|
// vector(this_type&& x, const Allocator& allocator)
|
|
// this_type& operator=(this_type&& x)
|
|
|
|
vector<TestObject> vector3TO33(3, TestObject(33));
|
|
vector<TestObject> toVectorA(eastl::move(vector3TO33));
|
|
EATEST_VERIFY((toVectorA.size() == 3) && (toVectorA.front().mX == 33) && (vector3TO33.size() == 0));
|
|
|
|
// The following is not as strong a test of this ctor as it could be. A stronger test would be to use
|
|
// IntanceAllocator with different instances.
|
|
vector<TestObject, MallocAllocator> vector4TO44(4, TestObject(44));
|
|
vector<TestObject, MallocAllocator> toVectorB(eastl::move(vector4TO44), MallocAllocator());
|
|
EATEST_VERIFY((toVectorB.size() == 4) && (toVectorB.front().mX == 44) && (vector4TO44.size() == 0));
|
|
|
|
vector<TestObject, MallocAllocator> vector5TO55(5, TestObject(55));
|
|
toVectorB = eastl::move(vector5TO55);
|
|
EATEST_VERIFY((toVectorB.size() == 5) && (toVectorB.front().mX == 55) && (vector5TO55.size() == 0));
|
|
|
|
// Should be able to emplace_back an item with const members (non-copyable)
|
|
eastl::vector<ItemWithConst> myVec2;
|
|
ItemWithConst& ref = myVec2.emplace_back(42);
|
|
EATEST_VERIFY(myVec2.back().i == 42);
|
|
EATEST_VERIFY(ref.i == 42);
|
|
}
|
|
|
|
{
|
|
using namespace eastl;
|
|
|
|
// pointer data();
|
|
// const_pointer data() const;
|
|
// reference front();
|
|
// const_reference front() const;
|
|
// reference back();
|
|
// const_reference back() const;
|
|
|
|
vector<int> intArray(10, 7);
|
|
intArray[0] = 10;
|
|
intArray[1] = 11;
|
|
intArray[2] = 12;
|
|
|
|
EATEST_VERIFY(intArray.data() == &intArray[0]);
|
|
EATEST_VERIFY(*intArray.data() == 10);
|
|
EATEST_VERIFY(intArray.front() == 10);
|
|
EATEST_VERIFY(intArray.back() == 7);
|
|
|
|
const vector<TestObject> toArrayC(10, TestObject(7));
|
|
|
|
EATEST_VERIFY(toArrayC.data() == &toArrayC[0]);
|
|
EATEST_VERIFY(*toArrayC.data() == TestObject(7));
|
|
EATEST_VERIFY(toArrayC.front() == TestObject(7));
|
|
EATEST_VERIFY(toArrayC.back() == TestObject(7));
|
|
}
|
|
|
|
{
|
|
using namespace eastl;
|
|
|
|
// iterator begin();
|
|
// const_iterator begin() const;
|
|
// iterator end();
|
|
// const_iterator end() const;
|
|
// reverse_iterator rbegin();
|
|
// const_reverse_iterator rbegin() const;
|
|
// reverse_iterator rend();
|
|
// const_reverse_iterator rend() const;
|
|
|
|
vector<int> intArray(20);
|
|
for (i = 0; i < 20; i++)
|
|
intArray[i] = (int)i;
|
|
|
|
i = 0;
|
|
for (vector<int>::iterator it = intArray.begin(); it != intArray.end(); ++it, ++i)
|
|
EATEST_VERIFY(*it == (int)i);
|
|
|
|
i = intArray.size() - 1;
|
|
for (vector<int>::reverse_iterator itr = intArray.rbegin(); itr != intArray.rend(); ++itr, --i)
|
|
EATEST_VERIFY(*itr == (int)i);
|
|
}
|
|
|
|
EATEST_VERIFY(TestObject::IsClear());
|
|
TestObject::Reset();
|
|
|
|
{
|
|
using namespace eastl;
|
|
|
|
// void swap(vector& x);
|
|
// void assign(size_type n, const value_type& value);
|
|
// void assign(InputIterator first, InputIterator last);
|
|
|
|
const int A[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
|
|
const int B[] = {99, 99, 99, 99, 99};
|
|
const size_t N = sizeof(A) / sizeof(int);
|
|
const size_t M = sizeof(B) / sizeof(int);
|
|
|
|
// assign from pointer range
|
|
vector<int> v3;
|
|
v3.assign(A, A + N);
|
|
EATEST_VERIFY(equal(v3.begin(), v3.end(), A));
|
|
EATEST_VERIFY(v3.size() == N);
|
|
|
|
// assign from iterator range
|
|
vector<int> v4;
|
|
v4.assign(v3.begin(), v3.end());
|
|
EATEST_VERIFY(equal(v4.begin(), v4.end(), A));
|
|
EATEST_VERIFY(equal(A, A + N, v4.begin()));
|
|
|
|
// assign from initializer range with resize
|
|
v4.assign(M, 99);
|
|
EATEST_VERIFY(equal(v4.begin(), v4.end(), B));
|
|
EATEST_VERIFY(equal(B, B + M, v4.begin()));
|
|
EATEST_VERIFY((v4.size() == M) && (M != N));
|
|
|
|
#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)
|
|
// void assign(std::initializer_list<T> ilist);
|
|
v4.assign({0, 1, 2, 3});
|
|
EATEST_VERIFY(v4.size() == 4);
|
|
EATEST_VERIFY((v4[0] == 0) && (v4[3] == 3));
|
|
#endif
|
|
}
|
|
|
|
EATEST_VERIFY(TestObject::IsClear());
|
|
TestObject::Reset();
|
|
|
|
{
|
|
using namespace eastl;
|
|
|
|
// reference operator[](size_type n);
|
|
// const_reference operator[](size_type n) const;
|
|
// reference at(size_type n);
|
|
// const_reference at(size_type n) const;
|
|
|
|
vector<int> intArray(5);
|
|
EATEST_VERIFY(intArray[3] == 0);
|
|
EATEST_VERIFY(intArray.at(3) == 0);
|
|
|
|
vector<TestObject> toArray(5);
|
|
EATEST_VERIFY(toArray[3] == TestObject(0));
|
|
EATEST_VERIFY(toArray.at(3) == TestObject(0));
|
|
|
|
#if EASTL_EXCEPTIONS_ENABLED
|
|
vector<TestObject> vec01(5);
|
|
|
|
try
|
|
{
|
|
TestObject& r01 = vec01.at(6);
|
|
EATEST_VERIFY(!(r01 == TestObject(0))); // Should not get here, as exception thrown.
|
|
}
|
|
catch (std::out_of_range&) { EATEST_VERIFY(true); }
|
|
catch (...) { EATEST_VERIFY(false); }
|
|
#endif
|
|
}
|
|
|
|
EATEST_VERIFY(TestObject::IsClear());
|
|
TestObject::Reset();
|
|
|
|
{
|
|
using namespace eastl;
|
|
|
|
// void push_back(const value_type& value);
|
|
// void push_back();
|
|
// void pop_back();
|
|
// void push_back(T&& value);
|
|
|
|
vector<int> intArray(6);
|
|
for (i = 0; i < 6; i++)
|
|
intArray[i] = (int)i;
|
|
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 6);
|
|
EATEST_VERIFY(intArray[5] == 5);
|
|
|
|
for (i = 0; i < 40; i++)
|
|
{
|
|
int& ref = intArray.push_back();
|
|
EATEST_VERIFY(&ref == &intArray.back());
|
|
ref = 98;
|
|
}
|
|
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 46);
|
|
EATEST_VERIFY(intArray[45] == 98);
|
|
|
|
for (i = 0; i < 40; i++)
|
|
intArray.push_back(99);
|
|
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 86);
|
|
EATEST_VERIFY(intArray[85] == 99);
|
|
|
|
for (i = 0; i < 30; i++)
|
|
intArray.pop_back();
|
|
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 56);
|
|
EATEST_VERIFY(intArray[5] == 5);
|
|
}
|
|
|
|
{
|
|
using namespace eastl;
|
|
|
|
// void* push_back_uninitialized();
|
|
|
|
int64_t toCount0 = TestObject::sTOCount;
|
|
|
|
vector<TestObject> vTO;
|
|
EATEST_VERIFY(TestObject::sTOCount == toCount0);
|
|
|
|
for (i = 0; i < 25; i++)
|
|
{
|
|
void* pTO = vTO.push_back_uninitialized();
|
|
EATEST_VERIFY(TestObject::sTOCount == (toCount0 + static_cast<int64_t>(i)));
|
|
|
|
new (pTO) TestObject((int)i);
|
|
EATEST_VERIFY(TestObject::sTOCount == (toCount0 + static_cast<int64_t>(i) + 1));
|
|
EATEST_VERIFY(vTO.back().mX == (int)i);
|
|
EATEST_VERIFY(vTO.validate());
|
|
}
|
|
}
|
|
|
|
{
|
|
using namespace eastl;
|
|
|
|
// template<class... Args>
|
|
// iterator emplace(const_iterator position, Args&&... args);
|
|
|
|
// template<class... Args>
|
|
// void emplace_back(Args&&... args);
|
|
|
|
// iterator insert(const_iterator position, value_type&& value);
|
|
// void push_back(value_type&& value);
|
|
|
|
TestObject::Reset();
|
|
|
|
vector<TestObject> toVectorA;
|
|
|
|
TestObject& ref = toVectorA.emplace_back(2, 3, 4);
|
|
EATEST_VERIFY((toVectorA.size() == 1) && (toVectorA.back().mX == (2 + 3 + 4)) &&
|
|
(TestObject::sTOCtorCount == 1));
|
|
EATEST_VERIFY(ref.mX == (2 + 3 + 4));
|
|
|
|
toVectorA.emplace(toVectorA.begin(), 3, 4, 5);
|
|
EATEST_VERIFY((toVectorA.size() == 2) && (toVectorA.front().mX == (3 + 4 + 5)) &&
|
|
(TestObject::sTOCtorCount == 3)); // 3 because the original count of 1, plus the existing vector
|
|
// element will be moved, plus the one being emplaced.
|
|
|
|
TestObject::Reset();
|
|
|
|
// void push_back(T&& x);
|
|
// iterator insert(const_iterator position, T&& x);
|
|
|
|
vector<TestObject> toVectorC;
|
|
|
|
toVectorC.push_back(TestObject(2, 3, 4));
|
|
EATEST_VERIFY((toVectorC.size() == 1) && (toVectorC.back().mX == (2 + 3 + 4)) &&
|
|
(TestObject::sTOMoveCtorCount == 1));
|
|
|
|
toVectorC.insert(toVectorC.begin(), TestObject(3, 4, 5));
|
|
EATEST_VERIFY((toVectorC.size() == 2) && (toVectorC.front().mX == (3 + 4 + 5)) &&
|
|
(TestObject::sTOMoveCtorCount == 3)); // 3 because the original count of 1, plus the existing
|
|
// vector element will be moved, plus the one being
|
|
// emplaced.
|
|
}
|
|
|
|
// We don't check for TestObject::IsClear because we messed with state above and don't currently have a matching set
|
|
// of ctors and dtors.
|
|
TestObject::Reset();
|
|
|
|
{
|
|
using namespace eastl;
|
|
|
|
// iterator erase(iterator position);
|
|
// iterator erase(iterator first, iterator last);
|
|
// iterator erase_unsorted(iterator position);
|
|
// iterator erase_first(const T& pos);
|
|
// iterator erase_first_unsorted(const T& pos);
|
|
// iterator erase_last(const T& pos);
|
|
// iterator erase_last_unsorted(const T& pos);
|
|
// void clear();
|
|
|
|
vector<int> intArray(20);
|
|
for (i = 0; i < 20; i++)
|
|
intArray[i] = (int)i;
|
|
|
|
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
|
|
|
|
intArray.erase(intArray.begin() +
|
|
10); // Becomes: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 19);
|
|
EATEST_VERIFY(intArray[0] == 0);
|
|
EATEST_VERIFY(intArray[10] == 11);
|
|
EATEST_VERIFY(intArray[18] == 19);
|
|
|
|
intArray.erase(intArray.begin() + 10,
|
|
intArray.begin() + 15); // Becomes: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 14);
|
|
EATEST_VERIFY(intArray[9] == 9);
|
|
EATEST_VERIFY(intArray[13] == 19);
|
|
|
|
intArray.erase(intArray.begin() + 1, intArray.begin() + 5); // Becomes: 0, 5, 6, 7, 8, 9, 16, 17, 18, 19
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 10);
|
|
EATEST_VERIFY(intArray[0] == 0);
|
|
EATEST_VERIFY(intArray[1] == 5);
|
|
EATEST_VERIFY(intArray[9] == 19);
|
|
|
|
intArray.erase(intArray.begin() + 7, intArray.begin() + 10); // Becomes: 0, 5, 6, 7, 8, 9, 16
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 7);
|
|
EATEST_VERIFY(intArray[0] == 0);
|
|
EATEST_VERIFY(intArray[1] == 5);
|
|
EATEST_VERIFY(intArray[6] == 16);
|
|
|
|
intArray.clear();
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.empty());
|
|
EATEST_VERIFY(intArray.size() == 0);
|
|
|
|
vector<TestObject> toArray(20);
|
|
for (i = 0; i < 20; i++)
|
|
toArray[i] = TestObject((int)i);
|
|
|
|
toArray.erase(toArray.begin() + 10);
|
|
EATEST_VERIFY(toArray.validate());
|
|
EATEST_VERIFY(toArray.size() == 19);
|
|
EATEST_VERIFY(toArray[10] == TestObject(11));
|
|
|
|
toArray.erase(toArray.begin() + 10, toArray.begin() + 15);
|
|
EATEST_VERIFY(toArray.validate());
|
|
EATEST_VERIFY(toArray.size() == 14);
|
|
EATEST_VERIFY(toArray[10] == TestObject(16));
|
|
|
|
toArray.clear();
|
|
EATEST_VERIFY(toArray.validate());
|
|
EATEST_VERIFY(toArray.empty());
|
|
EATEST_VERIFY(toArray.size() == 0);
|
|
|
|
// iterator erase_unsorted(iterator position);
|
|
intArray.resize(20);
|
|
for (i = 0; i < 20; i++)
|
|
intArray[i] = (int)i;
|
|
|
|
intArray.erase_unsorted(intArray.begin() + 0);
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 19);
|
|
EATEST_VERIFY(intArray[0] == 19);
|
|
EATEST_VERIFY(intArray[1] == 1);
|
|
EATEST_VERIFY(intArray[18] == 18);
|
|
|
|
intArray.erase_unsorted(intArray.begin() + 10);
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 18);
|
|
EATEST_VERIFY(intArray[0] == 19);
|
|
EATEST_VERIFY(intArray[10] == 18);
|
|
EATEST_VERIFY(intArray[17] == 17);
|
|
|
|
intArray.erase_unsorted(intArray.begin() + 17);
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 17);
|
|
EATEST_VERIFY(intArray[0] == 19);
|
|
EATEST_VERIFY(intArray[10] == 18);
|
|
EATEST_VERIFY(intArray[16] == 16);
|
|
|
|
// iterator erase_first(iterator position);
|
|
intArray.resize(20);
|
|
for (i = 0; i < 20; i++)
|
|
intArray[i] = (int)i % 3; // (i.e. 0,1,2,0,1,2...)
|
|
|
|
intArray.erase_first(1);
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 19);
|
|
EATEST_VERIFY(intArray[0] == 0);
|
|
EATEST_VERIFY(intArray[1] == 2);
|
|
EATEST_VERIFY(intArray[2] == 0);
|
|
EATEST_VERIFY(intArray[3] == 1);
|
|
EATEST_VERIFY(intArray[18] == 1);
|
|
|
|
intArray.erase_first(1);
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 18);
|
|
EATEST_VERIFY(intArray[0] == 0);
|
|
EATEST_VERIFY(intArray[1] == 2);
|
|
EATEST_VERIFY(intArray[2] == 0);
|
|
EATEST_VERIFY(intArray[3] == 2);
|
|
EATEST_VERIFY(intArray[17] == 1);
|
|
|
|
intArray.erase_first(0);
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 17);
|
|
EATEST_VERIFY(intArray[0] == 2);
|
|
EATEST_VERIFY(intArray[1] == 0);
|
|
EATEST_VERIFY(intArray[2] == 2);
|
|
EATEST_VERIFY(intArray[3] == 0);
|
|
EATEST_VERIFY(intArray[16] == 1);
|
|
|
|
// iterator erase_first_unsorted(const T& val);
|
|
intArray.resize(20);
|
|
for (i = 0; i < 20; i++)
|
|
intArray[i] = (int) i/2; // every two values are the same (i.e. 0,0,1,1,2,2,3,3...)
|
|
|
|
intArray.erase_first_unsorted(1);
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 19);
|
|
EATEST_VERIFY(intArray[0] == 0);
|
|
EATEST_VERIFY(intArray[1] == 0);
|
|
EATEST_VERIFY(intArray[2] == 9);
|
|
EATEST_VERIFY(intArray[3] == 1);
|
|
EATEST_VERIFY(intArray[18] == 9);
|
|
|
|
intArray.erase_first_unsorted(1);
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 18);
|
|
EATEST_VERIFY(intArray[0] == 0);
|
|
EATEST_VERIFY(intArray[1] == 0);
|
|
EATEST_VERIFY(intArray[2] == 9);
|
|
EATEST_VERIFY(intArray[3] == 9);
|
|
EATEST_VERIFY(intArray[17] == 8);
|
|
|
|
intArray.erase_first_unsorted(0);
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 17);
|
|
EATEST_VERIFY(intArray[0] == 8);
|
|
EATEST_VERIFY(intArray[1] == 0);
|
|
EATEST_VERIFY(intArray[2] == 9);
|
|
EATEST_VERIFY(intArray[3] == 9);
|
|
EATEST_VERIFY(intArray[16] == 8);
|
|
|
|
// iterator erase_last(const T& val);
|
|
intArray.resize(20);
|
|
for (i = 0; i < 20; i++)
|
|
intArray[i] = (int)i % 3; // (i.e. 0,1,2,0,1,2...)
|
|
|
|
intArray.erase_last(1);
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 19);
|
|
EATEST_VERIFY(intArray[0] == 0);
|
|
EATEST_VERIFY(intArray[1] == 1);
|
|
EATEST_VERIFY(intArray[2] == 2);
|
|
EATEST_VERIFY(intArray[3] == 0);
|
|
EATEST_VERIFY(intArray[15] == 0);
|
|
EATEST_VERIFY(intArray[16] == 1);
|
|
EATEST_VERIFY(intArray[17] == 2);
|
|
EATEST_VERIFY(intArray[18] == 0);
|
|
|
|
intArray.erase_last(1);
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 18);
|
|
EATEST_VERIFY(intArray[0] == 0);
|
|
EATEST_VERIFY(intArray[1] == 1);
|
|
EATEST_VERIFY(intArray[2] == 2);
|
|
EATEST_VERIFY(intArray[3] == 0);
|
|
EATEST_VERIFY(intArray[14] == 2);
|
|
EATEST_VERIFY(intArray[15] == 0);
|
|
EATEST_VERIFY(intArray[16] == 2);
|
|
EATEST_VERIFY(intArray[17] == 0);
|
|
|
|
intArray.erase_last(0);
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 17);
|
|
EATEST_VERIFY(intArray[0] == 0);
|
|
EATEST_VERIFY(intArray[1] == 1);
|
|
EATEST_VERIFY(intArray[2] == 2);
|
|
EATEST_VERIFY(intArray[3] == 0);
|
|
EATEST_VERIFY(intArray[13] == 1);
|
|
EATEST_VERIFY(intArray[14] == 2);
|
|
EATEST_VERIFY(intArray[15] == 0);
|
|
EATEST_VERIFY(intArray[16] == 2);
|
|
|
|
// iterator erase_last_unsorted(const T& val);
|
|
intArray.resize(20);
|
|
for (i = 0; i < 20; i++)
|
|
intArray[i] = (int)i / 2; // every two values are the same (i.e. 0,0,1,1,2,2,3,3...)
|
|
|
|
intArray.erase_last_unsorted(1);
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 19);
|
|
EATEST_VERIFY(intArray[0] == 0);
|
|
EATEST_VERIFY(intArray[1] == 0);
|
|
EATEST_VERIFY(intArray[2] == 1);
|
|
EATEST_VERIFY(intArray[3] == 9);
|
|
EATEST_VERIFY(intArray[18] == 9);
|
|
|
|
intArray.erase_last_unsorted(1);
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 18);
|
|
EATEST_VERIFY(intArray[0] == 0);
|
|
EATEST_VERIFY(intArray[1] == 0);
|
|
EATEST_VERIFY(intArray[2] == 9);
|
|
EATEST_VERIFY(intArray[3] == 9);
|
|
EATEST_VERIFY(intArray[17] == 8);
|
|
|
|
intArray.erase_last_unsorted(0);
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY(intArray.size() == 17);
|
|
EATEST_VERIFY(intArray[0] == 0);
|
|
EATEST_VERIFY(intArray[1] == 8);
|
|
EATEST_VERIFY(intArray[2] == 9);
|
|
EATEST_VERIFY(intArray[3] == 9);
|
|
EATEST_VERIFY(intArray[16] == 8);
|
|
}
|
|
|
|
EATEST_VERIFY(TestObject::IsClear());
|
|
TestObject::Reset();
|
|
|
|
{
|
|
using namespace eastl;
|
|
|
|
// iterator erase(reverse_iterator position);
|
|
// iterator erase(reverse_iterator first, reverse_iterator last);
|
|
// iterator erase_unsorted(reverse_iterator position);
|
|
|
|
vector<int> intVector;
|
|
|
|
for (i = 0; i < 20; i++)
|
|
intVector.push_back((int)i);
|
|
EATEST_VERIFY((intVector.size() == 20) && (intVector[0] == 0) && (intVector[19] == 19));
|
|
|
|
vector<int>::reverse_iterator r2A = intVector.rbegin();
|
|
vector<int>::reverse_iterator r2B = r2A + 3;
|
|
intVector.erase(r2A, r2B);
|
|
EATEST_VERIFY((intVector.size() == 17));
|
|
EATEST_VERIFY((intVector[0] == 0));
|
|
EATEST_VERIFY((intVector[16] == 16));
|
|
|
|
r2B = intVector.rend();
|
|
r2A = r2B - 3;
|
|
intVector.erase(r2A, r2B);
|
|
EATEST_VERIFY((intVector.size() == 14));
|
|
EATEST_VERIFY((intVector[0] == 3));
|
|
EATEST_VERIFY((intVector[13] == 16));
|
|
|
|
r2B = intVector.rend() - 1;
|
|
intVector.erase(r2B);
|
|
EATEST_VERIFY((intVector.size() == 13));
|
|
EATEST_VERIFY((intVector[0] == 4));
|
|
EATEST_VERIFY((intVector[12] == 16));
|
|
|
|
r2B = intVector.rbegin();
|
|
intVector.erase(r2B);
|
|
EATEST_VERIFY((intVector.size() == 12));
|
|
EATEST_VERIFY((intVector[0] == 4));
|
|
EATEST_VERIFY((intVector[11] == 15));
|
|
|
|
r2A = intVector.rbegin();
|
|
r2B = intVector.rend();
|
|
intVector.erase(r2A, r2B);
|
|
EATEST_VERIFY(intVector.size() == 0);
|
|
|
|
// iterator erase_unsorted(iterator position);
|
|
intVector.resize(20);
|
|
for (i = 0; i < 20; i++)
|
|
intVector[i] = (int)i;
|
|
|
|
intVector.erase_unsorted(intVector.rbegin() + 0);
|
|
EATEST_VERIFY(intVector.validate());
|
|
EATEST_VERIFY(intVector.size() == 19);
|
|
EATEST_VERIFY(intVector[0] == 0);
|
|
EATEST_VERIFY(intVector[10] == 10);
|
|
EATEST_VERIFY(intVector[18] == 18);
|
|
|
|
intVector.erase_unsorted(intVector.rbegin() + 10);
|
|
EATEST_VERIFY(intVector.validate());
|
|
EATEST_VERIFY(intVector.size() == 18);
|
|
EATEST_VERIFY(intVector[0] == 0);
|
|
EATEST_VERIFY(intVector[8] == 18);
|
|
EATEST_VERIFY(intVector[17] == 17);
|
|
|
|
intVector.erase_unsorted(intVector.rbegin() + 17);
|
|
EATEST_VERIFY(intVector.validate());
|
|
EATEST_VERIFY(intVector.size() == 17);
|
|
EATEST_VERIFY(intVector[0] == 17);
|
|
EATEST_VERIFY(intVector[8] == 18);
|
|
EATEST_VERIFY(intVector[16] == 16);
|
|
}
|
|
|
|
EATEST_VERIFY(TestObject::IsClear());
|
|
TestObject::Reset();
|
|
|
|
{
|
|
const int valueToRemove = 44;
|
|
int testValues[] = {42, 43, 44, 45, 46, 47};
|
|
|
|
eastl::vector<eastl::unique_ptr<int>> v;
|
|
|
|
for(auto& te : testValues)
|
|
v.push_back(eastl::make_unique<int>(te));
|
|
|
|
// remove 'valueToRemove' from the container
|
|
auto iterToRemove = eastl::find_if(v.begin(), v.end(), [&](eastl::unique_ptr<int>& e)
|
|
{ return *e == valueToRemove; });
|
|
v.erase_unsorted(iterToRemove);
|
|
EATEST_VERIFY(v.size() == 5);
|
|
|
|
// verify 'valueToRemove' is no longer in the container
|
|
EATEST_VERIFY(eastl::find_if(v.begin(), v.end(), [&](eastl::unique_ptr<int>& e)
|
|
{ return *e == valueToRemove; }) == v.end());
|
|
|
|
// verify all other expected values are in the container
|
|
for (auto& te : testValues)
|
|
{
|
|
if (te == valueToRemove)
|
|
continue;
|
|
|
|
EATEST_VERIFY(eastl::find_if(v.begin(), v.end(), [&](eastl::unique_ptr<int>& e)
|
|
{ return *e == te; }) != v.end());
|
|
}
|
|
}
|
|
|
|
EATEST_VERIFY(TestObject::IsClear());
|
|
TestObject::Reset();
|
|
|
|
{
|
|
using namespace eastl;
|
|
|
|
// iterator insert(iterator position, const value_type& value);
|
|
// iterator insert(iterator position, size_type n, const value_type& value);
|
|
// iterator insert(iterator position, InputIterator first, InputIterator last);
|
|
// iterator insert(const_iterator position, std::initializer_list<T> ilist);
|
|
|
|
vector<int> v(7, 13);
|
|
EATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), "vector", 13, 13, 13, 13, 13, 13, 13, -1));
|
|
|
|
// insert at end of size and capacity.
|
|
v.insert(v.end(), 99);
|
|
EATEST_VERIFY(v.validate());
|
|
EATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), "vector.insert", 13, 13, 13, 13, 13, 13, 13, 99, -1));
|
|
|
|
// insert at end of size.
|
|
v.reserve(30);
|
|
v.insert(v.end(), 999);
|
|
EATEST_VERIFY(v.validate());
|
|
EATEST_VERIFY(
|
|
VerifySequence(v.begin(), v.end(), int(), "vector.insert", 13, 13, 13, 13, 13, 13, 13, 99, 999, -1));
|
|
|
|
// Insert in middle.
|
|
vector<int>::iterator it = v.begin() + 7;
|
|
it = v.insert(it, 49);
|
|
EATEST_VERIFY(v.validate());
|
|
EATEST_VERIFY(
|
|
VerifySequence(v.begin(), v.end(), int(), "vector.insert", 13, 13, 13, 13, 13, 13, 13, 49, 99, 999, -1));
|
|
|
|
// Insert multiple copies
|
|
it = v.insert(v.begin() + 5, 3, 42);
|
|
EATEST_VERIFY(it == v.begin() + 5);
|
|
EATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), "vector.insert", 13, 13, 13, 13, 13, 42, 42, 42, 13, 13,
|
|
49, 99, 999, -1));
|
|
|
|
// Insert multiple copies with count == 0
|
|
vector<int>::iterator at = v.end();
|
|
it = v.insert(at, 0, 666);
|
|
EATEST_VERIFY(it == at);
|
|
EATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), "vector.insert", 13, 13, 13, 13, 13, 42, 42, 42, 13, 13,
|
|
49, 99, 999, -1));
|
|
// Insert iterator range
|
|
const int data[] = {2, 3, 4, 5};
|
|
it = v.insert(v.begin() + 1, data, data + 4);
|
|
EATEST_VERIFY(it == v.begin() + 1);
|
|
EATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), "vector.insert", 13, 2, 3, 4, 5, 13, 13, 13, 13, 42, 42,
|
|
42, 13, 13, 49, 99, 999, -1));
|
|
|
|
// Insert empty iterator range
|
|
at = v.begin() + 1;
|
|
it = v.insert(at, data + 4, data + 4);
|
|
EATEST_VERIFY(it == at);
|
|
EATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), "vector.insert", 13, 2, 3, 4, 5, 13, 13, 13, 13, 42, 42,
|
|
42, 13, 13, 49, 99, 999, -1));
|
|
|
|
// Insert with reallocation
|
|
it = v.insert(v.end() - 3, 6, 17);
|
|
EATEST_VERIFY(it == v.end() - (3 + 6));
|
|
EATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), "vector.insert", 13, 2, 3, 4, 5, 13, 13, 13, 13, 42, 42,
|
|
42, 13, 13, 17, 17, 17, 17, 17, 17, 49, 99, 999, -1));
|
|
|
|
// Single insert with reallocation
|
|
vector<int> v2;
|
|
v2.reserve(100);
|
|
v2.insert(v2.begin(), 100, 17);
|
|
EATEST_VERIFY(v2.size() == 100);
|
|
EATEST_VERIFY(v2[0] == 17);
|
|
v2.insert(v2.begin() + 50, 42);
|
|
EATEST_VERIFY(v2.size() == 101);
|
|
EATEST_VERIFY(v2[50] == 42);
|
|
|
|
// Test insertion of values that come from within the vector.
|
|
v.insert(v.end() - 3, v.end() - 5, v.end());
|
|
EATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), "vector.insert", 13, 2, 3, 4, 5, 13, 13, 13, 13, 42, 42,
|
|
42, 13, 13, 17, 17, 17, 17, 17, 17, 17, 17, 49, 99, 999, 49, 99, 999, -1));
|
|
|
|
v.insert(v.end() - 3, v.back());
|
|
EATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), "vector.insert", 13, 2, 3, 4, 5, 13, 13, 13, 13, 42, 42,
|
|
42, 13, 13, 17, 17, 17, 17, 17, 17, 17, 17, 49, 99, 999, 999, 49, 99, 999, -1));
|
|
|
|
v.insert(v.end() - 3, 2, v[v.size() - 3]);
|
|
EATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), "vector.insert", 13, 2, 3, 4, 5, 13, 13, 13, 13, 42, 42,
|
|
42, 13, 13, 17, 17, 17, 17, 17, 17, 17, 17, 49, 99, 999, 999, 49, 49, 49, 99, 999,
|
|
-1));
|
|
|
|
#if !defined(EASTL_STD_ITERATOR_CATEGORY_ENABLED) && !defined(EA_COMPILER_NO_STANDARD_CPP_LIBRARY)
|
|
// std::vector / eastl::vector
|
|
std::vector<TestObject> stdV(10);
|
|
eastl::vector<TestObject> eastlV(10);
|
|
|
|
eastlV.insert(eastlV.end(), stdV.begin(), stdV.end());
|
|
stdV.insert(stdV.end(), eastlV.begin(), eastlV.end());
|
|
|
|
EATEST_VERIFY(eastlV.size() == 20);
|
|
EATEST_VERIFY(stdV.size() == 30);
|
|
|
|
// std::string / eastl::vector
|
|
std::string stdString("blah");
|
|
eastl::vector<char8_t> eastlVString;
|
|
|
|
eastlVString.assign(stdString.begin(), stdString.end());
|
|
#endif
|
|
|
|
// iterator insert(const_iterator position, std::initializer_list<T> ilist);
|
|
#if !defined(EA_COMPILER_NO_INITIALIZER_LISTS)
|
|
// iterator insert(const_iterator position, std::initializer_list<T> ilist);
|
|
eastl::vector<float> floatVector;
|
|
|
|
floatVector.insert(floatVector.end(), {0, 1, 2, 3});
|
|
EATEST_VERIFY(floatVector.size() == 4);
|
|
EATEST_VERIFY((floatVector[0] == 0) && (floatVector[3] == 3));
|
|
#endif
|
|
}
|
|
|
|
EATEST_VERIFY(TestObject::IsClear());
|
|
TestObject::Reset();
|
|
|
|
{
|
|
// Test insert move objects
|
|
eastl::vector<TestObject> toVector1;
|
|
toVector1.reserve(20);
|
|
for(int idx = 0; idx < 2; ++idx)
|
|
toVector1.push_back(TestObject(idx));
|
|
|
|
eastl::vector<TestObject> toVector2;
|
|
for(int idx = 0; idx < 3; ++idx)
|
|
toVector2.push_back(TestObject(10 + idx));
|
|
|
|
// Insert more objects than the existing number using insert with iterator
|
|
TestObject::Reset();
|
|
eastl::vector<TestObject>::iterator it;
|
|
it = toVector1.insert(toVector1.begin(), toVector2.begin(), toVector2.end());
|
|
EATEST_VERIFY(it == toVector1.begin());
|
|
EATEST_VERIFY(VerifySequence(toVector1.begin(), toVector1.end(), int(), "vector.insert", 10, 11, 12, 0, 1, -1));
|
|
EATEST_VERIFY(TestObject::sTOMoveCtorCount + TestObject::sTOMoveAssignCount == 2 &&
|
|
TestObject::sTOCopyCtorCount + TestObject::sTOCopyAssignCount == 3); // Move 2 existing elements and copy the 3 inserted
|
|
|
|
eastl::vector<TestObject> toVector3;
|
|
toVector3.push_back(TestObject(20));
|
|
|
|
// Insert less objects than the existing number using insert with iterator
|
|
TestObject::Reset();
|
|
it = toVector1.insert(toVector1.begin(), toVector3.begin(), toVector3.end());
|
|
EATEST_VERIFY(VerifySequence(toVector1.begin(), toVector1.end(), int(), "vector.insert", 20, 10, 11, 12, 0, 1, -1));
|
|
EATEST_VERIFY(it == toVector1.begin());
|
|
EATEST_VERIFY(TestObject::sTOMoveCtorCount + TestObject::sTOMoveAssignCount == 5 &&
|
|
TestObject::sTOCopyCtorCount + TestObject::sTOCopyAssignCount == 1); // Move 5 existing elements and copy the 1 inserted
|
|
|
|
// Insert more objects than the existing number using insert without iterator
|
|
TestObject::Reset();
|
|
it = toVector1.insert(toVector1.begin(), 1, TestObject(17));
|
|
EATEST_VERIFY(it == toVector1.begin());
|
|
EATEST_VERIFY(VerifySequence(toVector1.begin(), toVector1.end(), int(), "vector.insert", 17, 20, 10, 11, 12, 0, 1, -1));
|
|
EATEST_VERIFY(TestObject::sTOMoveCtorCount + TestObject::sTOMoveAssignCount == 6 &&
|
|
TestObject::sTOCopyCtorCount + TestObject::sTOCopyAssignCount == 2); // Move 6 existing element and copy the 1 inserted +
|
|
// the temporary one inside the function
|
|
|
|
// Insert less objects than the existing number using insert without iterator
|
|
TestObject::Reset();
|
|
it = toVector1.insert(toVector1.begin(), 10, TestObject(18));
|
|
EATEST_VERIFY(it == toVector1.begin());
|
|
EATEST_VERIFY(VerifySequence(toVector1.begin(), toVector1.end(), int(), "vector.insert", 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 17, 20, 10, 11, 12, 0, 1, -1));
|
|
EATEST_VERIFY(TestObject::sTOMoveCtorCount + TestObject::sTOMoveAssignCount == 7 &&
|
|
TestObject::sTOCopyCtorCount + TestObject::sTOCopyAssignCount == 11); // Move 7 existing element and copy the 10 inserted +
|
|
// the temporary one inside the function
|
|
}
|
|
|
|
TestObject::Reset();
|
|
|
|
{
|
|
using namespace eastl;
|
|
|
|
// reserve / resize / capacity / clear
|
|
vector<int> v(10, 17);
|
|
v.reserve(20);
|
|
EATEST_VERIFY(v.validate());
|
|
EATEST_VERIFY(v.size() == 10);
|
|
EATEST_VERIFY(v.capacity() == 20);
|
|
|
|
v.resize(7); // Shrink
|
|
EATEST_VERIFY(v.validate());
|
|
EATEST_VERIFY(v.capacity() == 20);
|
|
|
|
v.resize(17); // Grow without reallocation
|
|
EATEST_VERIFY(v.validate());
|
|
EATEST_VERIFY(v.capacity() == 20);
|
|
|
|
v.resize(42); // Grow with reallocation
|
|
vector<int>::size_type c = v.capacity();
|
|
EATEST_VERIFY(v.validate());
|
|
EATEST_VERIFY(v[41] == 0);
|
|
EATEST_VERIFY(c >= 42);
|
|
|
|
v.resize(44, 19); // Grow with reallocation
|
|
EATEST_VERIFY(v.validate());
|
|
EATEST_VERIFY(v[43] == 19);
|
|
|
|
c = v.capacity();
|
|
v.clear();
|
|
EATEST_VERIFY(v.validate());
|
|
EATEST_VERIFY(v.empty());
|
|
EATEST_VERIFY(v.capacity() == c);
|
|
|
|
// How to shrink a vector's capacity to be equal to its size.
|
|
vector<int>(v).swap(v);
|
|
EATEST_VERIFY(v.validate());
|
|
EATEST_VERIFY(v.empty());
|
|
EATEST_VERIFY(v.capacity() == v.size());
|
|
|
|
// How to completely clear a vector (size = 0, capacity = 0, no allocation).
|
|
vector<int>().swap(v);
|
|
EATEST_VERIFY(v.validate());
|
|
EATEST_VERIFY(v.empty());
|
|
EATEST_VERIFY(v.capacity() == 0);
|
|
}
|
|
|
|
{ // set_capacity / reset
|
|
using namespace eastl;
|
|
|
|
const int intArray[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
|
|
const size_t kIntArraySize = sizeof(intArray) / sizeof(int);
|
|
|
|
vector<int> v(30);
|
|
EATEST_VERIFY(v.capacity() >= 30);
|
|
|
|
v.assign(intArray, intArray + kIntArraySize);
|
|
EATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), "vector.assign", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
|
|
13, 14, 15, 16, 17, -1));
|
|
|
|
// set_capacity
|
|
v.set_capacity();
|
|
EATEST_VERIFY(v.capacity() == v.size());
|
|
EATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), "vector.set_capacity", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
|
11, 12, 13, 14, 15, 16, 17, -1));
|
|
|
|
v.set_capacity(0);
|
|
EATEST_VERIFY(v.size() == 0);
|
|
EATEST_VERIFY(v.data() == NULL);
|
|
EATEST_VERIFY(v.capacity() == v.size());
|
|
|
|
// Test set_capacity doing a realloc of non-scalar class types.
|
|
eastl::vector<TestObject> toArray;
|
|
toArray.resize(16);
|
|
toArray.set_capacity(64);
|
|
EATEST_VERIFY(v.validate());
|
|
|
|
// reset_lose_memory
|
|
int* const pData = v.data();
|
|
vector<int>::size_type n = v.size();
|
|
vector<int>::allocator_type& allocator = v.get_allocator();
|
|
v.reset_lose_memory();
|
|
allocator.deallocate(pData, n);
|
|
EATEST_VERIFY(v.capacity() == 0);
|
|
EATEST_VERIFY(VerifySequence(v.begin(), v.end(), int(), "vector.reset", -1));
|
|
|
|
// Test set_capacity make a move when reducing size
|
|
vector<TestObject> toArray2(10, TestObject(7));
|
|
TestObject::Reset();
|
|
toArray2.set_capacity(5);
|
|
EATEST_VERIFY(TestObject::sTOMoveCtorCount == 5 &&
|
|
TestObject::sTOCopyCtorCount + TestObject::sTOCopyAssignCount == 0); // Move the 5 existing elements, no copy
|
|
EATEST_VERIFY(VerifySequence(toArray2.begin(), toArray2.end(), int(), "vector.set_capacity", 7, 7, 7, 7, 7, -1));
|
|
}
|
|
|
|
TestObject::Reset();
|
|
|
|
{
|
|
using namespace eastl;
|
|
|
|
// Regression for user-reported possible bug.
|
|
{
|
|
MallocAllocator::reset_all();
|
|
|
|
eastl::vector<int, MallocAllocator> v;
|
|
v.reserve(32); // does allocation
|
|
|
|
v.push_back(37); // may reallocate if we do enough of these to exceed 32
|
|
v.erase(v.begin());
|
|
|
|
v.set_capacity(0);
|
|
|
|
// Verify that all memory is freed by the set_capacity function.
|
|
EATEST_VERIFY((MallocAllocator::mAllocCountAll > 0) &&
|
|
(MallocAllocator::mAllocCountAll == MallocAllocator::mFreeCountAll));
|
|
|
|
MallocAllocator::reset_all();
|
|
}
|
|
|
|
{
|
|
MallocAllocator::reset_all();
|
|
|
|
eastl::vector<int, MallocAllocator> v;
|
|
v.reserve(32); // does allocation
|
|
|
|
for (int j = 0; j < 40; j++)
|
|
v.push_back(37); // may reallocate if we do enough of these to exceed 32
|
|
for (int k = 0; k < 40; k++)
|
|
v.erase(v.begin());
|
|
|
|
v.set_capacity(0);
|
|
|
|
// Verify that all memory is freed by the set_capacity function.
|
|
EATEST_VERIFY((MallocAllocator::mAllocCountAll > 0) &&
|
|
(MallocAllocator::mAllocCountAll == MallocAllocator::mFreeCountAll));
|
|
|
|
MallocAllocator::reset_all();
|
|
}
|
|
}
|
|
|
|
{
|
|
using namespace eastl;
|
|
|
|
// bool validate() const;
|
|
// bool validate_iterator(const_iterator i) const;
|
|
|
|
vector<int> intArray(20);
|
|
|
|
EATEST_VERIFY(intArray.validate());
|
|
EATEST_VERIFY((intArray.validate_iterator(intArray.begin()) & (isf_valid | isf_can_dereference)) != 0);
|
|
EATEST_VERIFY(intArray.validate_iterator(NULL) == isf_none);
|
|
}
|
|
|
|
{
|
|
using namespace eastl;
|
|
|
|
// global operators (==, !=, <, etc.)
|
|
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;
|
|
}
|
|
|
|
EATEST_VERIFY((intArray1 == intArray2));
|
|
EATEST_VERIFY(!(intArray1 != intArray2));
|
|
EATEST_VERIFY((intArray1 <= intArray2));
|
|
EATEST_VERIFY((intArray1 >= intArray2));
|
|
EATEST_VERIFY(!(intArray1 < intArray2));
|
|
EATEST_VERIFY(!(intArray1 > intArray2));
|
|
|
|
intArray1.push_back(100); // Make intArray1 less than intArray2.
|
|
intArray2.push_back(101);
|
|
|
|
EATEST_VERIFY(!(intArray1 == intArray2));
|
|
EATEST_VERIFY((intArray1 != intArray2));
|
|
EATEST_VERIFY((intArray1 <= intArray2));
|
|
EATEST_VERIFY(!(intArray1 >= intArray2));
|
|
EATEST_VERIFY((intArray1 < intArray2));
|
|
EATEST_VERIFY(!(intArray1 > intArray2));
|
|
}
|
|
|
|
{
|
|
using namespace eastl;
|
|
|
|
// Test vector<Align64>
|
|
|
|
// Aligned objects should be CustomAllocator instead of the default, because the
|
|
// EASTL default might be unable to do aligned allocations, but CustomAllocator always can.
|
|
vector<Align64, CustomAllocator> vA64(10);
|
|
|
|
vA64.resize(2);
|
|
EATEST_VERIFY(vA64.size() == 2);
|
|
|
|
vA64.push_back(Align64());
|
|
EATEST_VERIFY(vA64.size() == 3);
|
|
|
|
vA64.resize(0);
|
|
EATEST_VERIFY(vA64.size() == 0);
|
|
|
|
vA64.insert(vA64.begin(), Align64());
|
|
EATEST_VERIFY(vA64.size() == 1);
|
|
|
|
vA64.resize(20);
|
|
EATEST_VERIFY(vA64.size() == 20);
|
|
}
|
|
|
|
{
|
|
// Misc additional tests
|
|
|
|
eastl::vector<int> empty1;
|
|
EATEST_VERIFY(empty1.data() == NULL);
|
|
EATEST_VERIFY(empty1.size() == 0);
|
|
EATEST_VERIFY(empty1.capacity() == 0);
|
|
|
|
eastl::vector<int> empty2 = empty1;
|
|
EATEST_VERIFY(empty2.data() == NULL);
|
|
EATEST_VERIFY(empty2.size() == 0);
|
|
EATEST_VERIFY(empty2.capacity() == 0);
|
|
}
|
|
|
|
{ // Test whose purpose is to see if calling vector::size() in a const loop results in the compiler optimizing the
|
|
// size() call to outside the loop.
|
|
eastl::vector<TestObject> toArray;
|
|
|
|
toArray.resize(7);
|
|
|
|
for (i = 0; i < toArray.size(); i++)
|
|
{
|
|
TestObject& to = toArray[i];
|
|
|
|
if (to.mX == 99999)
|
|
to.mX++;
|
|
}
|
|
}
|
|
|
|
{ // Test assign from iterator type.
|
|
TestObject to;
|
|
eastl::vector<TestObject> toTest;
|
|
|
|
// InputIterator
|
|
demoted_iterator<TestObject*, eastl::forward_iterator_tag> toInput(&to);
|
|
toTest.assign(toInput, toInput);
|
|
|
|
// ForwardIterator
|
|
eastl::slist<TestObject> toSList;
|
|
toTest.assign(toSList.begin(), toSList.end());
|
|
|
|
// BidirectionalIterator
|
|
eastl::list<TestObject> toList;
|
|
toTest.assign(toList.begin(), toList.end());
|
|
|
|
// RandomAccessIterator
|
|
eastl::deque<TestObject> toDeque;
|
|
toTest.assign(toDeque.begin(), toDeque.end());
|
|
|
|
// ContiguousIterator (note: as of this writing, vector doesn't actually use contiguous_iterator_tag)
|
|
eastl::vector<TestObject> toArray;
|
|
toTest.assign(toArray.begin(), toArray.end());
|
|
}
|
|
|
|
EATEST_VERIFY(TestObject::IsClear());
|
|
TestObject::Reset();
|
|
|
|
{ // Test user report that they think they saw code like this leak memory.
|
|
eastl::vector<int> intTest;
|
|
|
|
intTest.push_back(1);
|
|
intTest = eastl::vector<int>();
|
|
|
|
eastl::vector<TestObject> toTest;
|
|
|
|
toTest.push_back(TestObject(1));
|
|
toTest = eastl::vector<TestObject>();
|
|
}
|
|
|
|
EATEST_VERIFY(TestObject::IsClear());
|
|
TestObject::Reset();
|
|
|
|
{ // Regression of user error report for the case of vector<const type>.
|
|
eastl::vector<int> ctorValues;
|
|
|
|
for (int v = 0; v < 10; v++)
|
|
ctorValues.push_back(v);
|
|
|
|
eastl::vector<const ConstType> testStruct(ctorValues.begin(), ctorValues.end());
|
|
eastl::vector<const int> testInt(ctorValues.begin(), ctorValues.end());
|
|
}
|
|
|
|
{ // Regression to verify that const vector works.
|
|
const eastl::vector<int> constIntVector1;
|
|
EATEST_VERIFY(constIntVector1.empty());
|
|
|
|
int intArray[3] = {37, 38, 39};
|
|
const eastl::vector<int> constIntVector2(intArray, intArray + 3);
|
|
EATEST_VERIFY(constIntVector2.size() == 3);
|
|
|
|
const eastl::vector<int> constIntVector3(4, 37);
|
|
EATEST_VERIFY(constIntVector3.size() == 4);
|
|
|
|
const eastl::vector<int> constIntVector4;
|
|
const eastl::vector<int> constIntVector5 = constIntVector4;
|
|
}
|
|
|
|
{ // Regression to verify that a bug fix for a vector optimization works.
|
|
eastl::vector<int> intVector1;
|
|
intVector1.reserve(128);
|
|
intVector1.resize(128, 37);
|
|
intVector1.push_back(intVector1.front());
|
|
EATEST_VERIFY(intVector1.back() == 37);
|
|
|
|
eastl::vector<int> intVector2;
|
|
intVector2.reserve(1024);
|
|
intVector2.resize(1024, 37);
|
|
intVector2.resize(2048, intVector2.front());
|
|
EATEST_VERIFY(intVector2.back() == 37);
|
|
}
|
|
|
|
{ // C++11 Range
|
|
// EABase 2.00.34+ has EA_COMPILER_NO_RANGE_BASED_FOR_LOOP, which we can check instead.
|
|
#if (defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1700)) || \
|
|
(defined(__clang__) && (EA_COMPILER_VERSION >= 300) && (__cplusplus >= 201103L)) || \
|
|
(defined(__GNUC__) && (EA_COMPILER_VERSION >= 4006) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
|
|
(__cplusplus >= 201103L)
|
|
|
|
eastl::vector<float> floatVector;
|
|
|
|
floatVector.push_back(0.0);
|
|
floatVector.push_back(1.0);
|
|
|
|
for (auto& f : floatVector)
|
|
f += 1.0;
|
|
|
|
EATEST_VERIFY(floatVector.back() == 2.0);
|
|
#endif
|
|
}
|
|
|
|
{
|
|
// C++11 cbegin, cend, crbegin, crend
|
|
#if !defined(EA_COMPILER_NO_AUTO)
|
|
// float vector
|
|
eastl::vector<float> floatVector;
|
|
|
|
auto cb = floatVector.cbegin();
|
|
auto ce = floatVector.cend();
|
|
auto crb = floatVector.crbegin();
|
|
auto cre = floatVector.crend();
|
|
|
|
EATEST_VERIFY(eastl::distance(cb, ce) == 0);
|
|
EATEST_VERIFY(eastl::distance(crb, cre) == 0);
|
|
|
|
// const float vector
|
|
const eastl::vector<float> cFloatVector;
|
|
|
|
auto ccb = cFloatVector.cbegin();
|
|
auto cce = cFloatVector.cend();
|
|
auto ccrb = cFloatVector.crbegin();
|
|
auto ccre = cFloatVector.crend();
|
|
|
|
EATEST_VERIFY(eastl::distance(ccb, cce) == 0);
|
|
EATEST_VERIFY(eastl::distance(ccrb, ccre) == 0);
|
|
|
|
#endif
|
|
}
|
|
|
|
{
|
|
// Regression for failure in DoRealloc's use of uninitialize_move.
|
|
using namespace eastl;
|
|
|
|
const eastl::string str0 = "TestString0";
|
|
vector<eastl::string> v(1, str0);
|
|
vector<eastl::string> v_copy;
|
|
|
|
// Test operator=
|
|
v_copy = v;
|
|
EATEST_VERIFY_MSG(v_copy.size() == 1, "vector string8 copy size");
|
|
EATEST_VERIFY_MSG(eastl::find(v_copy.begin(), v_copy.end(), str0) != v_copy.end(), "vector copy string8");
|
|
EATEST_VERIFY_MSG(v.size() == 1, "vector string8 copy size");
|
|
EATEST_VERIFY_MSG(eastl::find(v.begin(), v.end(), str0) != v.end(), "vector copy string8");
|
|
|
|
// Test assign.
|
|
v.clear();
|
|
v.push_back(str0);
|
|
v_copy.assign(v.begin(), v.end());
|
|
EATEST_VERIFY_MSG(v_copy.size() == 1, "vector string8 copy size");
|
|
EATEST_VERIFY_MSG(eastl::find(v_copy.begin(), v_copy.end(), str0) != v_copy.end(), "vector copy string8");
|
|
EATEST_VERIFY_MSG(v.size() == 1, "vector string8 copy size");
|
|
EATEST_VERIFY_MSG(eastl::find(v.begin(), v.end(), str0) != v.end(), "vector copy string8");
|
|
}
|
|
|
|
{
|
|
// Regression of vector::operator= for the case of EASTL_ALLOCATOR_COPY_ENABLED=1
|
|
// For this test we need to use InstanceAllocator to create two containers of the same
|
|
// type but with different and unequal allocator instances. The bug was that when
|
|
// EASTL_ALLOCATOR_COPY_ENABLED was enabled operator=(this_type& x) assigned x.mAllocator
|
|
// to this and then proceeded to assign member elements from x to this. That's invalid
|
|
// because the existing elements of this were allocated by a different allocator and
|
|
// will be freed in the future with the allocator copied from x.
|
|
// The test below should work for the case of EASTL_ALLOCATOR_COPY_ENABLED == 0 or 1.
|
|
InstanceAllocator::reset_all();
|
|
|
|
InstanceAllocator ia0((uint8_t)0);
|
|
InstanceAllocator ia1((uint8_t)1);
|
|
|
|
eastl::vector<int, InstanceAllocator> v0((eastl_size_t)1, (int)0, ia0);
|
|
eastl::vector<int, InstanceAllocator> v1((eastl_size_t)1, (int)1, ia1);
|
|
|
|
EATEST_VERIFY((v0.front() == 0) && (v1.front() == 1));
|
|
#if EASTL_ALLOCATOR_COPY_ENABLED
|
|
EATEST_VERIFY(v0.get_allocator() != v1.get_allocator());
|
|
#endif
|
|
v0 = v1;
|
|
EATEST_VERIFY((v0.front() == 1) && (v1.front() == 1));
|
|
EATEST_VERIFY(InstanceAllocator::mMismatchCount == 0);
|
|
EATEST_VERIFY(v0.validate());
|
|
EATEST_VERIFY(v1.validate());
|
|
#if EASTL_ALLOCATOR_COPY_ENABLED
|
|
EATEST_VERIFY(v0.get_allocator() == v1.get_allocator());
|
|
#endif
|
|
}
|
|
|
|
{
|
|
// Test shrink_to_fit
|
|
eastl::vector<int> v;
|
|
EATEST_VERIFY(v.capacity() == 0);
|
|
v.resize(100);
|
|
EATEST_VERIFY(v.capacity() == 100);
|
|
v.clear();
|
|
EATEST_VERIFY(v.capacity() == 100);
|
|
v.shrink_to_fit();
|
|
EATEST_VERIFY(v.capacity() == 0);
|
|
}
|
|
|
|
{
|
|
// Regression for compilation errors found and fixed when integrating into Frostbite.
|
|
int j = 7;
|
|
|
|
eastl::vector<StructWithConstInt> v1;
|
|
v1.push_back(StructWithConstInt(j));
|
|
|
|
eastl::vector<StructWithConstRefToInt> v2;
|
|
v2.push_back(StructWithConstRefToInt(j));
|
|
}
|
|
|
|
{
|
|
// Regression for issue with vector containing non-copyable values reported by user
|
|
eastl::vector<testmovable> moveablevec;
|
|
testmovable moveable;
|
|
moveablevec.insert(moveablevec.end(), eastl::move(moveable));
|
|
}
|
|
|
|
{
|
|
// Calling erase of empty range should not call a move assignment to self
|
|
eastl::vector<TestMoveAssignToSelf> v1;
|
|
v1.push_back(TestMoveAssignToSelf());
|
|
EATEST_VERIFY(!v1[0].mMovedToSelf);
|
|
v1.erase(v1.begin(), v1.begin());
|
|
EATEST_VERIFY(!v1[0].mMovedToSelf);
|
|
}
|
|
|
|
#if defined(EASTL_TEST_CONCEPT_IMPLS)
|
|
{
|
|
// vector default constructor should require no more than Destructible
|
|
eastl::vector<Destructible> v1;
|
|
EATEST_VERIFY(v1.empty());
|
|
|
|
// some basic vector operations (data(), capacity(), size(), empty(), clear(), erase()) should impose no
|
|
// requirements beyond Destructible
|
|
EATEST_VERIFY(v1.empty());
|
|
EATEST_VERIFY(v1.size() == 0);
|
|
EATEST_VERIFY(v1.capacity() == 0);
|
|
EATEST_VERIFY(eastl::distance(v1.data(), v1.data() + v1.size()) == 0);
|
|
v1.clear();
|
|
}
|
|
|
|
{
|
|
// vector default constructor should work with DefaultConstructible T
|
|
eastl::vector<DefaultConstructible> v1;
|
|
EATEST_VERIFY(v1.empty());
|
|
}
|
|
|
|
{
|
|
// vector constructor that takes an initial size should only require DefaultConstructible T
|
|
eastl::vector<DefaultConstructible> v2(2);
|
|
EATEST_VERIFY(v2.size() == 2 && v2[0].value == v2[1].value &&
|
|
v2[0].value == DefaultConstructible::defaultValue);
|
|
}
|
|
|
|
{
|
|
// vector constructor taking an initial size and a value should only require CopyConstructible
|
|
eastl::vector<CopyConstructible> v3(2, CopyConstructible::Create());
|
|
EATEST_VERIFY(v3.size() == 2 && v3[0].value == v3[1].value && v3[0].value == CopyConstructible::defaultValue);
|
|
|
|
// vector constructor taking a pair of iterators should work for CopyConstructible
|
|
eastl::vector<CopyConstructible> v4(cbegin(v3), cend(v3));
|
|
EATEST_VERIFY(v4.size() == 2 && v4[0].value == v4[1].value && v4[0].value == CopyConstructible::defaultValue);
|
|
}
|
|
|
|
{
|
|
// vector::reserve() should only require MoveInsertible
|
|
eastl::vector<MoveConstructible> v5;
|
|
v5.reserve(2);
|
|
v5.push_back(MoveConstructible::Create());
|
|
v5.push_back(MoveConstructible::Create());
|
|
EATEST_VERIFY(v5.size() == 2 && v5[0].value == v5[1].value && v5[0].value == MoveConstructible::defaultValue);
|
|
v5.pop_back();
|
|
|
|
// vector::shrink_to_fit() should only require MoveInsertible
|
|
v5.shrink_to_fit();
|
|
EATEST_VERIFY(v5.size() == 1 && v5.capacity() == 1 && v5[0].value == MoveConstructible::defaultValue);
|
|
}
|
|
|
|
{
|
|
// vector constructor taking a pair of iterators should only require MoveConstructible
|
|
MoveConstructible moveConstructibleArray[] = {MoveConstructible::Create()};
|
|
eastl::vector<MoveConstructible> v7(
|
|
eastl::move_iterator<MoveConstructible*>(eastl::begin(moveConstructibleArray)),
|
|
eastl::move_iterator<MoveConstructible*>(eastl::end(moveConstructibleArray)));
|
|
EATEST_VERIFY(v7.size() == 1 && v7[0].value == MoveConstructible::defaultValue);
|
|
}
|
|
|
|
{
|
|
// vector::swap() should only require Destructible. We also test with DefaultConstructible as it gives us a
|
|
// testable result.
|
|
|
|
eastl::vector<Destructible> v4, v5;
|
|
eastl::swap(v4, v5);
|
|
EATEST_VERIFY(v4.empty() && v5.empty());
|
|
|
|
eastl::vector<DefaultConstructible> v6(1), v7(2);
|
|
eastl::swap(v6, v7);
|
|
EATEST_VERIFY(v6.size() == 2 && v7.size() == 1);
|
|
}
|
|
|
|
{
|
|
// vector::resize() should only require MoveInsertable and DefaultInsertable
|
|
eastl::vector<MoveAndDefaultConstructible> v8;
|
|
v8.resize(2);
|
|
EATEST_VERIFY(v8.size() == 2 && v8[0].value == v8[1].value && v8[0].value ==
|
|
MoveAndDefaultConstructible::defaultValue);
|
|
}
|
|
|
|
{
|
|
eastl::vector<MoveAssignable> v1;
|
|
// vector::insert(pos, rv) should only require MoveAssignable
|
|
v1.insert(begin(v1), MoveAssignable::Create());
|
|
EATEST_VERIFY(v1.size() == 1 && v1.front().value == MoveAssignable::defaultValue);
|
|
// vector::erase(pos) should only require MoveAssignable
|
|
v1.erase(begin(v1));
|
|
EATEST_VERIFY(v1.empty());
|
|
}
|
|
#endif // EASTL_TEST_CONCEPT_IMPLS
|
|
|
|
{
|
|
// validates our vector implementation does not use 'operator<' on input iterators during vector construction.
|
|
//
|
|
struct container_value_type { int data; };
|
|
struct container_with_custom_iterator
|
|
{
|
|
struct iterator
|
|
{
|
|
typedef eastl::input_iterator_tag iterator_category;
|
|
typedef int value_type;
|
|
typedef ptrdiff_t difference_type;
|
|
typedef int* pointer;
|
|
typedef int& reference;
|
|
|
|
bool operator!=(const iterator&) const { return false; }
|
|
iterator& operator++() { return *this; }
|
|
iterator operator++(int) { return *this; }
|
|
container_value_type operator*() { return {}; }
|
|
};
|
|
|
|
container_with_custom_iterator() EA_NOEXCEPT {}
|
|
|
|
iterator begin() const { return {}; }
|
|
iterator end() const { return {}; }
|
|
bool empty() const { return false; }
|
|
|
|
private:
|
|
eastl::vector<container_value_type> m_vector;
|
|
};
|
|
|
|
static_assert(!is_less_comparable<container_with_custom_iterator::iterator>::value, "type cannot support comparison by '<' for this test");
|
|
container_with_custom_iterator ci;
|
|
eastl::vector<container_value_type> v2(ci.begin(), ci.end());
|
|
}
|
|
|
|
// If the legacy code path is enabled we cannot handle non-copyable types
|
|
#ifndef EASTL_VECTOR_LEGACY_SWAP_BEHAVIOUR_REQUIRES_COPY_CTOR
|
|
// unique_ptr tests
|
|
{
|
|
// Simple move-assignment test to prevent regressions where eastl::vector utilizes operations on T that are not necessary.
|
|
{
|
|
eastl::vector<eastl::unique_ptr<int>> v1;
|
|
eastl::vector<eastl::unique_ptr<int>> v2;
|
|
v2 = eastl::move(v1);
|
|
}
|
|
|
|
{
|
|
// This test verifies that eastl::vector can handle the move-assignment case where its utilizes two
|
|
// different allocator instances that do not compare equal. An example of an allocator that compares equal
|
|
// but isn't the same object instance is an allocator that shares the same memory allocation mechanism (eg.
|
|
// malloc). The memory allocated from one instance can be freed by another instance in the case where
|
|
// allocators compare equal. This test is verifying functionality in the opposite case where allocators
|
|
// instances do not compare equal and must clean up its own allocated memory.
|
|
InstanceAllocator::reset_all();
|
|
{
|
|
InstanceAllocator a1(uint8_t(0)), a2(uint8_t(1));
|
|
eastl::vector<eastl::unique_ptr<int>, InstanceAllocator> v1(a1);
|
|
eastl::vector<eastl::unique_ptr<int>, InstanceAllocator> v2(a2);
|
|
|
|
VERIFY(v1.get_allocator() != v2.get_allocator());
|
|
|
|
// add some data in the vector so we can move it to the other vector.
|
|
v1.push_back(nullptr);
|
|
v1.push_back(nullptr);
|
|
v1.push_back(nullptr);
|
|
v1.push_back(nullptr);
|
|
|
|
VERIFY(!v1.empty() && v2.empty());
|
|
v2 = eastl::move(v1);
|
|
VERIFY(v1.empty() && !v2.empty());
|
|
v1.swap(v2);
|
|
VERIFY(!v1.empty() && v2.empty());
|
|
}
|
|
VERIFY(InstanceAllocator::mMismatchCount == 0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
{
|
|
// CustomAllocator has no data members which reduces the size of an eastl::vector via the empty base class optimization.
|
|
typedef eastl::vector<int, CustomAllocator> EboVector;
|
|
static_assert(sizeof(EboVector) == 3 * sizeof(void*), "");
|
|
}
|
|
|
|
// eastl::erase / eastl::erase_if tests
|
|
{
|
|
{
|
|
eastl::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9};
|
|
|
|
eastl::erase(v, 5);
|
|
VERIFY((v == eastl::vector<int> {1, 2, 3, 4, 6, 7, 8, 9}));
|
|
|
|
eastl::erase(v, 2);
|
|
VERIFY((v == eastl::vector<int> {1, 3, 4, 6, 7, 8, 9}));
|
|
|
|
eastl::erase(v, 9);
|
|
VERIFY((v == eastl::vector<int> {1, 3, 4, 6, 7, 8}));
|
|
}
|
|
|
|
{
|
|
eastl::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9};
|
|
eastl::erase_if(v, [](auto i) { return i % 2 == 0; });
|
|
VERIFY((v == eastl::vector<int>{1, 3, 5, 7, 9}));
|
|
}
|
|
}
|
|
|
|
return nErrorCount;
|
|
}
|