From b2d923a7af2751e4e41036093c3f839524f01a49 Mon Sep 17 00:00:00 2001 From: "Winkler, Max" Date: Tue, 9 Jun 2020 19:00:00 +0200 Subject: [PATCH] [EASTL 3.16.07] EASTL: fixing spelling mistake in eastl::basic_string Fix for insertion_sort() doing a --(BiDirectionalIterator) which is an illegal operation and causes crashes on containers such as eastl::deque. eastl::optional_storage - remove unneeded union and trivial type initialization since we use eastl::aligned_storage_t, remove unreferenced internal member function EASTL: resolving 32-bit eastl_size_t compiler error EASTL: EASTL_ALIGN_OF porting to C++11 alignof keyword. EASTL_EMPTY_REFERENCE_ASSERT_ENABLED when enabled would not assert when taking a reference to an empty container. Example, eastl::vector[0] would not assert that a null reference was being taken if the vector was empty. EASTL: fixing shared_ptr compiler error when passing nullptr with a custom deleter lambda --- include/EASTL/bonus/list_map.h | 32 +++---- include/EASTL/bonus/tuple_vector.h | 52 ++++++----- include/EASTL/deque.h | 46 +++++----- include/EASTL/internal/config.h | 22 ++--- include/EASTL/list.h | 32 +++---- include/EASTL/optional.h | 101 +++++++-------------- include/EASTL/shared_ptr.h | 84 +++++++++--------- include/EASTL/sort.h | 136 +++++------------------------ include/EASTL/span.h | 4 +- include/EASTL/string.h | 40 ++++----- include/EASTL/vector.h | 50 ++++++----- test/source/TestSmartPtr.cpp | 9 ++ test/source/TestSort.cpp | 13 ++- 13 files changed, 255 insertions(+), 366 deletions(-) diff --git a/include/EASTL/bonus/list_map.h b/include/EASTL/bonus/list_map.h index ca733204..8a080d6d 100644 --- a/include/EASTL/bonus/list_map.h +++ b/include/EASTL/bonus/list_map.h @@ -600,11 +600,11 @@ namespace eastl inline typename list_map::reference list_map::front() { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(static_cast(mNode.mpNext) == &mNode)) + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(static_cast(mNode.mpNext) == &mNode)) EASTL_FAIL_MSG("list_map::front -- empty container"); + #else + // We allow the user to reference an empty container. #endif return static_cast(mNode.mpNext)->mValue; @@ -614,11 +614,11 @@ namespace eastl inline typename list_map::const_reference list_map::front() const { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(static_cast(mNode.mpNext) == &mNode)) + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(static_cast(mNode.mpNext) == &mNode)) EASTL_FAIL_MSG("list_map::front -- empty container"); + #else + // We allow the user to reference an empty container. #endif return static_cast(mNode.mpNext)->mValue; @@ -628,11 +628,11 @@ namespace eastl inline typename list_map::reference list_map::back() { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(static_cast(mNode.mpNext) == &mNode)) + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(static_cast(mNode.mpNext) == &mNode)) EASTL_FAIL_MSG("list_map::back -- empty container"); + #else + // We allow the user to reference an empty container. #endif return static_cast(mNode.mpPrev)->mValue; @@ -642,11 +642,11 @@ namespace eastl inline typename list_map::const_reference list_map::back() const { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(static_cast(mNode.mpNext) == &mNode)) + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(static_cast(mNode.mpNext) == &mNode)) EASTL_FAIL_MSG("list_map::back -- empty container"); + #else + // We allow the user to reference an empty container. #endif return static_cast(mNode.mpPrev)->mValue; diff --git a/include/EASTL/bonus/tuple_vector.h b/include/EASTL/bonus/tuple_vector.h index 3df3e1dd..e55fb6a9 100644 --- a/include/EASTL/bonus/tuple_vector.h +++ b/include/EASTL/bonus/tuple_vector.h @@ -1131,45 +1131,49 @@ class TupleVecImpl, Ts...> : public TupleV reference_tuple front() { -#if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. -#elif EASTL_ASSERT_ENABLED - if (EASTL_UNLIKELY(mNumElements == 0)) // We don't allow the user to reference an empty container. - EASTL_FAIL_MSG("tuple_vector::front -- empty vector"); -#endif + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(mNumElements == 0)) // We don't allow the user to reference an empty container. + EASTL_FAIL_MSG("tuple_vector::front -- empty vector"); + #else + // We allow the user to reference an empty container. + #endif + return at(0); } const_reference_tuple front() const { -#if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. -#elif EASTL_ASSERT_ENABLED - if (EASTL_UNLIKELY(mNumElements == 0)) // We don't allow the user to reference an empty container. - EASTL_FAIL_MSG("tuple_vector::front -- empty vector"); -#endif + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(mNumElements == 0)) // We don't allow the user to reference an empty container. + EASTL_FAIL_MSG("tuple_vector::front -- empty vector"); + #else + // We allow the user to reference an empty container. + #endif + return at(0); } reference_tuple back() { -#if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. -#elif EASTL_ASSERT_ENABLED - if (EASTL_UNLIKELY(mNumElements == 0)) // We don't allow the user to reference an empty container. - EASTL_FAIL_MSG("tuple_vector::back -- empty vector"); -#endif + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(mNumElements == 0)) // We don't allow the user to reference an empty container. + EASTL_FAIL_MSG("tuple_vector::back -- empty vector"); + #else + // We allow the user to reference an empty container. + #endif + return at(size() - 1); } const_reference_tuple back() const { -#if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. -#elif EASTL_ASSERT_ENABLED - if (EASTL_UNLIKELY(mNumElements == 0)) // We don't allow the user to reference an empty container. - EASTL_FAIL_MSG("tuple_vector::back -- empty vector"); -#endif + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(mNumElements == 0)) // We don't allow the user to reference an empty container. + EASTL_FAIL_MSG("tuple_vector::back -- empty vector"); + #else + // We allow the user to reference an empty container. + #endif + return at(size() - 1); } diff --git a/include/EASTL/deque.h b/include/EASTL/deque.h index 313594b6..4568a0bf 100644 --- a/include/EASTL/deque.h +++ b/include/EASTL/deque.h @@ -1514,11 +1514,12 @@ namespace eastl typename deque::reference deque::operator[](size_type n) { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED // We allow the user to use a reference to v[0] of an empty container. - if(EASTL_UNLIKELY((n != 0) && n >= (size_type)(mItEnd - mItBegin))) + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(n >= (size_type)(mItEnd - mItBegin))) EASTL_FAIL_MSG("deque::operator[] -- out of range"); #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(n >= (size_type)(mItEnd - mItBegin))) + // We allow taking a reference to deque[0] + if (EASTL_UNLIKELY((n != 0) && n >= (size_type)(mItEnd - mItBegin))) EASTL_FAIL_MSG("deque::operator[] -- out of range"); #endif @@ -1536,11 +1537,12 @@ namespace eastl typename deque::const_reference deque::operator[](size_type n) const { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED // We allow the user to use a reference to v[0] of an empty container. - if(EASTL_UNLIKELY((n != 0) && n >= (size_type)(mItEnd - mItBegin))) + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(n >= (size_type)(mItEnd - mItBegin))) EASTL_FAIL_MSG("deque::operator[] -- out of range"); #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(n >= (size_type)(mItEnd - mItBegin))) + // We allow the user to use a reference to deque[0] of an empty container. + if (EASTL_UNLIKELY((n != 0) && n >= (size_type)(mItEnd - mItBegin))) EASTL_FAIL_MSG("deque::operator[] -- out of range"); #endif @@ -1588,11 +1590,11 @@ namespace eastl typename deque::reference deque::front() { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY((size_type)(mItEnd == mItBegin))) + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY((size_type)(mItEnd == mItBegin))) EASTL_FAIL_MSG("deque::front -- empty deque"); + #else + // We allow the user to reference an empty container. #endif return *mItBegin; @@ -1603,11 +1605,11 @@ namespace eastl typename deque::const_reference deque::front() const { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY((size_type)(mItEnd == mItBegin))) + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY((size_type)(mItEnd == mItBegin))) EASTL_FAIL_MSG("deque::front -- empty deque"); + #else + // We allow the user to reference an empty container. #endif return *mItBegin; @@ -1618,11 +1620,11 @@ namespace eastl typename deque::reference deque::back() { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY((size_type)(mItEnd == mItBegin))) + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY((size_type)(mItEnd == mItBegin))) EASTL_FAIL_MSG("deque::back -- empty deque"); + #else + // We allow the user to reference an empty container. #endif return *iterator(mItEnd, typename iterator::Decrement()); @@ -1633,11 +1635,11 @@ namespace eastl typename deque::const_reference deque::back() const { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY((size_type)(mItEnd == mItBegin))) + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY((size_type)(mItEnd == mItBegin))) EASTL_FAIL_MSG("deque::back -- empty deque"); + #else + // We allow the user to reference an empty container. #endif return *iterator(mItEnd, typename iterator::Decrement()); diff --git a/include/EASTL/internal/config.h b/include/EASTL/internal/config.h index 4138af49..a824609a 100644 --- a/include/EASTL/internal/config.h +++ b/include/EASTL/internal/config.h @@ -89,8 +89,8 @@ /////////////////////////////////////////////////////////////////////////////// #ifndef EASTL_VERSION - #define EASTL_VERSION "3.16.05" - #define EASTL_VERSION_N 31605 + #define EASTL_VERSION "3.16.07" + #define EASTL_VERSION_N 31607 #endif @@ -449,6 +449,8 @@ namespace eastl // In practice it's often easier and more efficient to do this than to write // extra code to check if the container is empty. // +// NOTE: If this is enabled, EASTL_ASSERT_ENABLED must also be enabled +// // Example usage: // template // inline typename vector::reference @@ -1544,13 +1546,8 @@ namespace eastl // size_t alignment = EASTL_ALIGN_OF(int); // /////////////////////////////////////////////////////////////////////////////// - #ifndef EASTL_ALIGN_OF - #if !defined(__GNUC__) || (__GNUC__ >= 3) // GCC 2.x doesn't do __alignof correctly all the time. - #define EASTL_ALIGN_OF __alignof - #else - #define EASTL_ALIGN_OF(type) ((size_t)offsetof(struct{ char c; type m; }, m)) - #endif + #define EASTL_ALIGN_OF alignof #endif @@ -1768,6 +1765,7 @@ typedef EASTL_SSIZE_T eastl_ssize_t; // Signed version of eastl_size_t. Concept #endif #endif + /// EASTL_TUPLE_ENABLED /// EASTL tuple implementation depends on variadic template support #if EASTL_VARIADIC_TEMPLATES_ENABLED && !defined(EA_COMPILER_NO_TEMPLATE_ALIASES) @@ -1776,14 +1774,6 @@ typedef EASTL_SSIZE_T eastl_ssize_t; // Signed version of eastl_size_t. Concept #define EASTL_TUPLE_ENABLED 0 #endif -/// EA_ONCE -/// -/// This is a fix for the EA_ONCE define that's broken in EABase versions prior to 2.00.40 -/// -#ifndef EA_ONCE - #define EA_ONCE() -#endif - /// EASTL_FUNCTION_ENABLED /// diff --git a/include/EASTL/list.h b/include/EASTL/list.h index 8099c242..023bccee 100644 --- a/include/EASTL/list.h +++ b/include/EASTL/list.h @@ -995,11 +995,11 @@ namespace eastl inline typename list::reference list::front() { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(static_cast(internalNode().mpNext) == &internalNode())) + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(static_cast(internalNode().mpNext) == &internalNode())) EASTL_FAIL_MSG("list::front -- empty container"); + #else + // We allow the user to reference an empty container. #endif return static_cast(internalNode().mpNext)->mValue; @@ -1010,11 +1010,11 @@ namespace eastl inline typename list::const_reference list::front() const { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(static_cast(internalNode().mpNext) == &internalNode())) + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(static_cast(internalNode().mpNext) == &internalNode())) EASTL_FAIL_MSG("list::front -- empty container"); + #else + // We allow the user to reference an empty container. #endif return static_cast(internalNode().mpNext)->mValue; @@ -1025,11 +1025,11 @@ namespace eastl inline typename list::reference list::back() { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(static_cast(internalNode().mpNext) == &internalNode())) + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(static_cast(internalNode().mpNext) == &internalNode())) EASTL_FAIL_MSG("list::back -- empty container"); + #else + // We allow the user to reference an empty container. #endif return static_cast(internalNode().mpPrev)->mValue; @@ -1040,11 +1040,11 @@ namespace eastl inline typename list::const_reference list::back() const { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(static_cast(internalNode().mpNext) == &internalNode())) + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(static_cast(internalNode().mpNext) == &internalNode())) EASTL_FAIL_MSG("list::back -- empty container"); + #else + // We allow the user to reference an empty container. #endif return static_cast(internalNode().mpPrev)->mValue; diff --git a/include/EASTL/optional.h b/include/EASTL/optional.h index 10f653eb..e967f985 100644 --- a/include/EASTL/optional.h +++ b/include/EASTL/optional.h @@ -3,18 +3,18 @@ /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -// This file implements the class template optional that represents optional objects. +// This file implements the class template optional that represents optional objects. // // An optional object is an object that contains the storage for another object and // manages the lifetime of this contained object, if any. The contained object may be // initialized after the optional object has been initialized, and may be destroyed before -// the optional object has been destroyed. +// the optional object has been destroyed. // // Any instance of optional at any given time either contains a value or does not // contain a value. When an instance of optional contains a value, it means that an // object of type T, referred to as the optional object's contained value, is allocated // within the storage of the optional object. Implementations are not permitted to use -// additional storage, such as dynamic memory, to allocate its contained value. +// additional storage, such as dynamic memory, to allocate its contained value. // // The contained value is allocated in the optional storage suitably // aligned for the type T. When an object of type optional is contextually converted to @@ -46,7 +46,7 @@ EA_DISABLE_VC_WARNING(4582 4583) // constructor/destructor is not implicitly cal namespace eastl { #if EASTL_EXCEPTIONS_ENABLED - #define EASTL_OPTIONAL_NOEXCEPT + #define EASTL_OPTIONAL_NOEXCEPT #else #define EASTL_OPTIONAL_NOEXCEPT EA_NOEXCEPT #endif @@ -87,21 +87,16 @@ namespace eastl { typedef typename eastl::remove_const::type value_type; - inline optional_storage() EA_NOEXCEPT : empty_val('\0') {} + optional_storage() EA_NOEXCEPT = default; - template>> - inline optional_storage(const optional_storage& other) : engaged(other.engaged) - { - auto* pOtherValue = reinterpret_cast(eastl::addressof(other.val)); - ::new (eastl::addressof(val)) value_type(*pOtherValue); - } - - inline optional_storage(const value_type& v) : engaged(true) + inline optional_storage(const value_type& v) + : engaged(true) { ::new (eastl::addressof(val)) value_type(v); } - inline optional_storage(value_type&& v) : engaged(true) + inline optional_storage(value_type&& v) + : engaged(true) { ::new (eastl::addressof(val)) value_type(eastl::move(v)); } @@ -110,16 +105,6 @@ namespace eastl { if (engaged) destruct_value(); - - // engaged = false; // probably not needed as we are destroying the object - } - - template>> - inline optional_storage& operator=(const optional_storage& other) - { - auto* pOtherValue = reinterpret_cast(eastl::addressof(other.val)); - ::new (eastl::addressof(val)) value_type(*pOtherValue); - return *this; } template @@ -141,13 +126,7 @@ namespace eastl inline void destruct_value() { (*(value_type*)eastl::addressof(val)).~value_type(); } - // This union exists to support trivial types that do not require constructors/destructors to be called. - // The eastl::optional type will set the empty_val in this case to "initialize" its member data. - union - { - eastl::aligned_storage_t> val; - char empty_val; - }; + eastl::aligned_storage_t> val; bool engaged = false; }; @@ -162,20 +141,16 @@ namespace eastl { typedef eastl::remove_const_t value_type; - inline optional_storage() EA_NOEXCEPT : empty_val('\0') {} + optional_storage() EA_NOEXCEPT = default; - inline optional_storage(const optional_storage& other) : engaged(other.engaged) - { - auto* pOtherValue = reinterpret_cast(eastl::addressof(other.val)); - ::new (eastl::addressof(val)) value_type(*pOtherValue); - } - - inline optional_storage(const value_type& v) : engaged(true) + inline optional_storage(const value_type& v) + : engaged(true) { ::new (eastl::addressof(val)) value_type(v); } - inline optional_storage(value_type&& v) : engaged(true) + inline optional_storage(value_type&& v) + : engaged(true) { ::new (eastl::addressof(val)) value_type(eastl::move(v)); } @@ -187,19 +162,13 @@ namespace eastl // if (engaged) // destruct_value(); // } - - inline optional_storage& operator=(const optional_storage& other) - { - auto* pOtherValue = reinterpret_cast(eastl::addressof(other.val)); - ::new (eastl::addressof(val)) value_type(*pOtherValue); - return *this; - } + ~optional_storage() EA_NOEXCEPT = default; template inline explicit optional_storage(in_place_t, Args&&... args) : engaged(true) { - new (eastl::addressof(val)) value_type{eastl::forward(args)...}; + ::new (eastl::addressof(val)) value_type{eastl::forward(args)...}; } template ilist, Args&&... args) : engaged(true) { - new (eastl::addressof(val)) value_type{ilist, eastl::forward(args)...}; + ::new (eastl::addressof(val)) value_type{ilist, eastl::forward(args)...}; } inline void destruct_value() {} // no implementation necessary since T is trivially destructible. - // This union exists to support trivial types that do not require constructors/destructors to be called. - // The eastl::optional type will set the empty_val in this case to "initialize" its member data. - union - { - eastl::aligned_storage_t> val; - char empty_val; - }; + eastl::aligned_storage_t> val; bool engaged = false; }; } // namespace Internal @@ -306,7 +269,7 @@ namespace eastl return *this; } - inline optional& operator=(const optional& other) + inline optional& operator=(const optional& other) { auto* pOtherValue = reinterpret_cast(eastl::addressof(other.val)); if (engaged == other.engaged) @@ -464,7 +427,7 @@ namespace eastl inline T* get_value_address() EASTL_OPTIONAL_NOEXCEPT { #if EASTL_EXCEPTIONS_ENABLED - if(!engaged) + if(!engaged) throw bad_optional_access(); #elif EASTL_ASSERT_ENABLED EASTL_ASSERT_MSG(engaged, "no value to retrieve"); @@ -475,7 +438,7 @@ namespace eastl inline const T* get_value_address() const EASTL_OPTIONAL_NOEXCEPT { #if EASTL_EXCEPTIONS_ENABLED - if(!engaged) + if(!engaged) throw bad_optional_access(); #elif EASTL_ASSERT_ENABLED EASTL_ASSERT_MSG(engaged, "no value to retrieve"); @@ -486,7 +449,7 @@ namespace eastl inline value_type& get_value_ref() EASTL_OPTIONAL_NOEXCEPT { #if EASTL_EXCEPTIONS_ENABLED - if(!engaged) + if(!engaged) throw bad_optional_access(); #elif EASTL_ASSERT_ENABLED EASTL_ASSERT_MSG(engaged, "no value to retrieve"); @@ -497,7 +460,7 @@ namespace eastl inline const value_type& get_value_ref() const EASTL_OPTIONAL_NOEXCEPT { #if EASTL_EXCEPTIONS_ENABLED - if(!engaged) + if(!engaged) throw bad_optional_access(); #elif EASTL_ASSERT_ENABLED EASTL_ASSERT_MSG(engaged, "no value to retrieve"); @@ -508,7 +471,7 @@ namespace eastl inline value_type&& get_rvalue_ref() EASTL_OPTIONAL_NOEXCEPT { #if EASTL_EXCEPTIONS_ENABLED - if(!engaged) + if(!engaged) throw bad_optional_access(); #elif EASTL_ASSERT_ENABLED EASTL_ASSERT_MSG(engaged, "no value to retrieve"); @@ -519,7 +482,7 @@ namespace eastl /////////////////////////////////////////////////////////////////////////////// - /// global swap + /// global swap /// template void swap(optional& lhs, optional& rhs) EA_NOEXCEPT_IF(EA_NOEXCEPT(lhs.swap(rhs))) @@ -527,7 +490,7 @@ namespace eastl /////////////////////////////////////////////////////////////////////////////// - /// global comparisions + /// global comparisions /// /// http://en.cppreference.com/w/cpp/utility/optional/operator_cmp /// @@ -538,7 +501,7 @@ namespace eastl template inline EA_CONSTEXPR bool operator==(const optional& lhs, const optional& rhs) { - // NOTE: + // NOTE: // // Code collapsed onto a single line to satisfy requirements for constexpr expressions // being a single line return statement. @@ -557,7 +520,7 @@ namespace eastl template inline EA_CONSTEXPR bool operator<(const optional& lhs, const optional& rhs) { - // NOTE: + // NOTE: // // Code collapsed onto a single line to satisify requirements for constexpr expressions // being a single line return statement. @@ -695,7 +658,7 @@ namespace eastl /////////////////////////////////////////////////////////////////////////////// - /// hash + /// hash /// template struct hash> @@ -735,11 +698,11 @@ namespace eastl } - #undef EASTL_OPTIONAL_NOEXCEPT + #undef EASTL_OPTIONAL_NOEXCEPT } // namespace eastl EA_RESTORE_VC_WARNING() -#endif // EASTL_OPTIONAL_ENABLED +#endif // EASTL_OPTIONAL_ENABLED #endif // EASTL_OPTIONAL_H diff --git a/include/EASTL/shared_ptr.h b/include/EASTL/shared_ptr.h index 943c70bf..b1b94e9b 100644 --- a/include/EASTL/shared_ptr.h +++ b/include/EASTL/shared_ptr.h @@ -196,7 +196,7 @@ namespace eastl } } - return NULL; + return nullptr; } @@ -224,7 +224,7 @@ namespace eastl void free_value() EA_NOEXCEPT { mDeleter(mValue); - mValue = NULL; + mValue = nullptr; } void free_ref_count_sp() EA_NOEXCEPT @@ -237,7 +237,7 @@ namespace eastl #if EASTL_RTTI_ENABLED void* get_deleter(const std::type_info& type) const EA_NOEXCEPT { - return (type == typeid(deleter_type)) ? (void*)&mDeleter : NULL; + return (type == typeid(deleter_type)) ? (void*)&mDeleter : nullptr; } #else void* get_deleter() const EA_NOEXCEPT @@ -288,12 +288,12 @@ namespace eastl #if EASTL_RTTI_ENABLED void* get_deleter(const std::type_info&) const EA_NOEXCEPT { - return NULL; // Default base implementation. + return nullptr; // Default base implementation. } #else void* get_deleter() const EA_NOEXCEPT { - return NULL; + return nullptr; } #endif }; @@ -380,8 +380,8 @@ namespace eastl /// Initializes and "empty" shared_ptr. /// Postcondition: use_count() == zero and get() == 0 shared_ptr() EA_NOEXCEPT - : mpValue(NULL), - mpRefCount(NULL) + : mpValue(nullptr), + mpRefCount(nullptr) { // Intentionally leaving mpRefCount as NULL. Can't allocate here due to noexcept. } @@ -397,7 +397,7 @@ namespace eastl template explicit shared_ptr(U* pValue, typename eastl::enable_if::value>::type* = 0) - : mpValue(NULL), mpRefCount(NULL) // alloc_internal will set this. + : mpValue(nullptr), mpRefCount(nullptr) // alloc_internal will set this. { // We explicitly use default_delete. You can use the other version of this constructor to provide a // custom version. @@ -411,8 +411,8 @@ namespace eastl shared_ptr(std::nullptr_t) EA_NOEXCEPT - : mpValue(NULL), - mpRefCount(NULL) + : mpValue(nullptr), + mpRefCount(nullptr) { // Intentionally leaving mpRefCount as NULL. Can't allocate here due to noexcept. } @@ -431,16 +431,16 @@ namespace eastl shared_ptr(U* pValue, Deleter deleter, typename eastl::enable_if::value>::type* = 0) - : mpValue(NULL), mpRefCount(NULL) + : mpValue(nullptr), mpRefCount(nullptr) { alloc_internal(pValue, default_allocator_type(), eastl::move(deleter)); } template shared_ptr(std::nullptr_t, Deleter deleter) - : mpValue(NULL), mpRefCount(NULL) // alloc_internal will set this. + : mpValue(nullptr), mpRefCount(nullptr) // alloc_internal will set this. { - alloc_internal(NULL, default_allocator_type(), eastl::move(deleter)); + alloc_internal(nullptr, default_allocator_type(), eastl::move(deleter)); } @@ -458,17 +458,17 @@ namespace eastl Deleter deleter, const Allocator& allocator, typename eastl::enable_if::value>::type* = 0) - : mpValue(NULL), mpRefCount(NULL) // alloc_internal will set this. + : mpValue(nullptr), mpRefCount(nullptr) // alloc_internal will set this. { alloc_internal(pValue, eastl::move(allocator), eastl::move(deleter)); } template shared_ptr(std::nullptr_t, Deleter deleter, Allocator allocator) - : mpValue(NULL), - mpRefCount(NULL) // alloc_internal will set this. + : mpValue(nullptr), + mpRefCount(nullptr) // alloc_internal will set this. { - alloc_internal(NULL, eastl::move(allocator), eastl::move(deleter)); + alloc_internal(nullptr, eastl::move(allocator), eastl::move(deleter)); } @@ -532,8 +532,8 @@ namespace eastl : mpValue(sharedPtr.mpValue), mpRefCount(sharedPtr.mpRefCount) { - sharedPtr.mpValue = NULL; - sharedPtr.mpRefCount = NULL; + sharedPtr.mpValue = nullptr; + sharedPtr.mpRefCount = nullptr; } @@ -543,8 +543,8 @@ namespace eastl : mpValue(sharedPtr.mpValue), mpRefCount(sharedPtr.mpRefCount) { - sharedPtr.mpValue = NULL; - sharedPtr.mpRefCount = NULL; + sharedPtr.mpValue = nullptr; + sharedPtr.mpRefCount = nullptr; } // unique_ptr constructor @@ -552,7 +552,7 @@ namespace eastl shared_ptr(unique_ptr&& uniquePtr, typename eastl::enable_if::value && !is_lvalue_reference::value && eastl::is_convertible::value>::type* = 0) - : mpValue(NULL), mpRefCount(NULL) + : mpValue(nullptr), mpRefCount(nullptr) { alloc_internal(uniquePtr.release(), default_allocator_type(), uniquePtr.get_deleter()); } @@ -564,7 +564,7 @@ namespace eastl const Allocator& allocator, typename eastl::enable_if::value && !is_lvalue_reference::value && eastl::is_convertible::value>::type* = 0) - : mpValue(NULL), mpRefCount(NULL) + : mpValue(nullptr), mpRefCount(nullptr) { alloc_internal(uniquePtr.release(), allocator, uniquePtr.get_deleter()); } @@ -583,7 +583,7 @@ namespace eastl { if (!mpRefCount) { - mpValue = NULL; // Question: Is it right for us to NULL this or not? + mpValue = nullptr; // Question: Is it right for us to NULL this or not? #if EASTL_EXCEPTIONS_ENABLED throw eastl::bad_weak_ptr(); @@ -606,8 +606,8 @@ namespace eastl // shared_ptr(const shared_ptr& sharedPtr, element_type* pValue) constructor). #if EASTL_DEBUG - mpValue = NULL; - mpRefCount = NULL; + mpValue = nullptr; + mpRefCount = nullptr; #endif } @@ -845,14 +845,14 @@ namespace eastl Deleter* get_deleter() const EA_NOEXCEPT { #if EASTL_RTTI_ENABLED - return mpRefCount ? static_cast(mpRefCount->get_deleter(typeid(typename remove_cv::type))) : NULL; + return mpRefCount ? static_cast(mpRefCount->get_deleter(typeid(typename remove_cv::type))) : nullptr; #else // This is probably unsafe but without typeid there is no way to ensure that the // stored deleter is actually of the templated Deleter type. - return NULL; + return nullptr; // Alternatively: - // return mpRefCount ? static_cast(mpRefCount->get_deleter()) : NULL; + // return mpRefCount ? static_cast(mpRefCount->get_deleter()) : nullptr; #endif } @@ -865,12 +865,12 @@ namespace eastl { if(mpValue) return &this_type::get; - return NULL; + return nullptr; } bool operator!() const EA_NOEXCEPT { - return (mpValue == NULL); + return (mpValue == nullptr); } #else /// Explicit operator bool @@ -881,7 +881,7 @@ namespace eastl /// ++*ptr; explicit operator bool() const EA_NOEXCEPT { - return (mpValue != NULL); + return (mpValue != nullptr); } #endif @@ -903,9 +903,9 @@ namespace eastl // Handles the allocating of mpRefCount, while assigning mpValue. // The provided pValue may be NULL, as with constructing with a deleter and allocator but NULL pointer. template - void alloc_internal(U* pValue, Allocator allocator, Deleter deleter) + void alloc_internal(U pValue, Allocator allocator, Deleter deleter) { - typedef ref_count_sp_t ref_count_type; + typedef ref_count_sp_t ref_count_type; #if EASTL_EXCEPTIONS_ENABLED try @@ -1371,8 +1371,8 @@ namespace eastl public: /// weak_ptr weak_ptr() EA_NOEXCEPT - : mpValue(NULL), - mpRefCount(NULL) + : mpValue(nullptr), + mpRefCount(nullptr) { } @@ -1394,8 +1394,8 @@ namespace eastl : mpValue(weakPtr.mpValue), mpRefCount(weakPtr.mpRefCount) { - weakPtr.mpValue = NULL; - weakPtr.mpRefCount = NULL; + weakPtr.mpValue = nullptr; + weakPtr.mpRefCount = nullptr; } @@ -1419,8 +1419,8 @@ namespace eastl : mpValue(weakPtr.mpValue), mpRefCount(weakPtr.mpRefCount) { - weakPtr.mpValue = NULL; - weakPtr.mpRefCount = NULL; + weakPtr.mpValue = nullptr; + weakPtr.mpRefCount = nullptr; } @@ -1527,8 +1527,8 @@ namespace eastl if(mpRefCount) mpRefCount->weak_release(); - mpValue = NULL; - mpRefCount = NULL; + mpValue = nullptr; + mpRefCount = nullptr; } void swap(this_type& weakPtr) diff --git a/include/EASTL/sort.h b/include/EASTL/sort.h index 7c0c6e8f..5b3fe6e0 100644 --- a/include/EASTL/sort.h +++ b/include/EASTL/sort.h @@ -43,6 +43,7 @@ #include +#include #include #include #include @@ -215,41 +216,40 @@ namespace eastl } - + ////////////////////////////////////////////////////////////////////////////// /// insertion_sort /// - /// Since insertion_sort requires that the data be addressed with a BidirectionalIterator and - /// not the more flexible RandomAccessIterator, we implement the sort by doing a for loop within - /// a for loop. If we were to specialize this for a RandomAccessIterator, we could replace the - /// inner for loop with a call to upper_bound, which would be faster. + /// insertion_sort is an O(n^2) stable sorting algorithm that starts at the + /// (k + 1) element and assumes the first (k) elements are sorted. + /// Then copy_backwards from (k + 1) to the begining any elements where the + /// (k + 1) element is less than [0, k] elements. The position of k when + /// (k + 1) element is not less than k is the sorted position of the (k + 1) element. /// + /// Example With Intermediate Steps: + /// (k + 1) == 2 : [3, 2, 1] -> [3, 3, 1] -> [2, 3, 1] + /// (k + 1) == 1 : [2, 3, 1] -> [2, 3, 3] -> [2, 2, 3] -> [1, 2, 3] + /// : [1, 2, 3] template void insertion_sort(BidirectionalIterator first, BidirectionalIterator last, StrictWeakOrdering compare) { typedef typename eastl::iterator_traits::value_type value_type; - if(first != last) // if the range is non-empty... + if (first != last) { - BidirectionalIterator iCurrent, iNext, iSorted = first; + BidirectionalIterator i = first; - for(++iSorted; iSorted != last; ++iSorted) + for (++i; i != last; ++i) { - value_type temp(eastl::forward(*iSorted)); - - iNext = iCurrent = iSorted; + value_type insertValue(eastl::move(*i)); + BidirectionalIterator insertPosition = i; - // Note: The following loop has a problem: it can decrement iCurrent to before 'first'. - // It doesn't dereference the iterator, but std STL disallows that operation. This isn't - // a problem for EASTL containers and ranges, as they support a single decrement of first, - // but std STL iterators may have a problem with it. Dinkumware STL, for example, will assert. - // To do: Fix this loop to not decrement like so. - for(--iCurrent; (iNext != first) && compare(temp, *iCurrent); --iNext, --iCurrent) + for (BidirectionalIterator movePosition = i; movePosition != first && compare(insertValue, *(--movePosition)); --insertPosition) { - EASTL_VALIDATE_COMPARE(!compare(*iCurrent, temp)); // Validate that the compare function is sane. - *iNext = eastl::forward(*iCurrent); + EASTL_VALIDATE_COMPARE(!compare(*movePosition, insertValue)); + *insertPosition = eastl::move(*movePosition); } - *iNext = eastl::forward(temp); + *insertPosition = eastl::move(insertValue); } } } // insertion_sort @@ -258,105 +258,13 @@ namespace eastl template void insertion_sort(BidirectionalIterator first, BidirectionalIterator last) { - typedef typename eastl::iterator_traits::value_type value_type; - - if(first != last) - { - BidirectionalIterator iCurrent, iNext, iSorted = first; - - for(++iSorted; iSorted != last; ++iSorted) - { - value_type temp(eastl::forward(*iSorted)); - - iNext = iCurrent = iSorted; + typedef eastl::less::value_type> Less; - // Note: The following loop has a problem: it can decrement iCurrent to before 'first'. - // It doesn't dereference the iterator, but std STL disallows that operation. This isn't - // a problem for EASTL containers and ranges, as they support a single decrement of first, - // but std STL iterators may have a problem with it. Dinkumware STL, for example, will assert. - // To do: Fix this loop to not decrement like so. - for(--iCurrent; (iNext != first) && (temp < *iCurrent); --iNext, --iCurrent) - { - EASTL_VALIDATE_COMPARE(!(*iCurrent < temp)); // Validate that the compare function is sane. - *iNext = eastl::forward(*iCurrent); - } + insertion_sort(first, last, Less()); - *iNext = eastl::forward(temp); - } - } } // insertion_sort - #if 0 /* - // STLPort-like variation of insertion_sort. Doesn't seem to run quite as fast for small runs. - // - template - void insertion_sort(RandomAccessIterator first, RandomAccessIterator last, Compare compare) - { - if(first != last) - { - for(RandomAccessIterator i = first + 1; i != last; ++i) - { - const typename eastl::iterator_traits::value_type value(*i); - - if(compare(value, *first)) - { - EASTL_VALIDATE_COMPARE(!compare(*first, value)); // Validate that the compare function is sane. - eastl::copy_backward(first, i, i + 1); - *first = value; - } - else - { - RandomAccessIterator end(i), prev(i); - - for(--prev; compare(value, *prev); --end, --prev) - { - EASTL_VALIDATE_COMPARE(!compare(*prev, value)); // Validate that the compare function is sane. - *end = *prev; - } - - *end = value; - } - } - } - } - - - // STLPort-like variation of insertion_sort. Doesn't seem to run quite as fast for small runs. - // - template - void insertion_sort(RandomAccessIterator first, RandomAccessIterator last) - { - if(first != last) - { - for(RandomAccessIterator i = first + 1; i != last; ++i) - { - const typename eastl::iterator_traits::value_type value(*i); - - if(value < *first) - { - EASTL_VALIDATE_COMPARE(!(*first < value)); // Validate that the compare function is sane. - eastl::copy_backward(first, i, i + 1); - *first = value; - } - else - { - RandomAccessIterator end(i), prev(i); - - for(--prev; value < *prev; --end, --prev) - { - EASTL_VALIDATE_COMPARE(!(*prev < value)); // Validate that the compare function is sane. - *end = *prev; - } - - *end = value; - } - } - } - } */ - #endif - - /// shell_sort /// /// Implements the ShellSort algorithm. This algorithm is a serious algorithm for larger diff --git a/include/EASTL/span.h b/include/EASTL/span.h index 625c1163..1f3b9b42 100644 --- a/include/EASTL/span.h +++ b/include/EASTL/span.h @@ -404,7 +404,7 @@ namespace eastl EASTL_ASSERT_MSG(bounds_check(Offset), "undefined behaviour accessing out of bounds"); EASTL_ASSERT_MSG(Count == dynamic_extent || Count <= (size() - Offset), "undefined behaviour exceeding size of span"); - return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count}; + return {data() + Offset, eastl_size_t(Count == dynamic_extent ? size() - Offset : Count)}; } template @@ -414,7 +414,7 @@ namespace eastl EASTL_ASSERT_MSG(bounds_check(offset), "undefined behaviour accessing out of bounds"); EASTL_ASSERT_MSG(count == dynamic_extent || count <= (size() - offset), "undefined behaviour exceeding size of span"); - return {data() + offset, count == dynamic_extent ? size() - offset : count}; + return {data() + offset, eastl_size_t(count == dynamic_extent ? size() - offset : count)}; } template diff --git a/include/EASTL/string.h b/include/EASTL/string.h index ce83df3d..6b8baac7 100644 --- a/include/EASTL/string.h +++ b/include/EASTL/string.h @@ -450,12 +450,12 @@ namespace eastl inline value_type* HeapCapacityPtr() EA_NOEXCEPT { return heap.mpBegin + GetHeapCapacity(); } inline const value_type* HeapCapacityPtr() const EA_NOEXCEPT { return heap.mpBegin + GetHeapCapacity(); } - inline value_type* SSOCapcityPtr() EA_NOEXCEPT { return sso.mData + SSOLayout::SSO_CAPACITY; } - inline const value_type* SSOCapcityPtr() const EA_NOEXCEPT { return sso.mData + SSOLayout::SSO_CAPACITY; } + inline value_type* SSOCapacityPtr() EA_NOEXCEPT { return sso.mData + SSOLayout::SSO_CAPACITY; } + inline const value_type* SSOCapacityPtr() const EA_NOEXCEPT { return sso.mData + SSOLayout::SSO_CAPACITY; } // Points to end of the buffer at the terminating '0', *ptr == '0' <- only true when size() == capacity() - inline value_type* CapacityPtr() EA_NOEXCEPT { return IsHeap() ? HeapCapacityPtr() : SSOCapcityPtr(); } - inline const value_type* CapacityPtr() const EA_NOEXCEPT { return IsHeap() ? HeapCapacityPtr() : SSOCapcityPtr(); } + inline value_type* CapacityPtr() EA_NOEXCEPT { return IsHeap() ? HeapCapacityPtr() : SSOCapacityPtr(); } + inline const value_type* CapacityPtr() const EA_NOEXCEPT { return IsHeap() ? HeapCapacityPtr() : SSOCapacityPtr(); } inline void SetHeapBeginPtr(value_type* pBegin) EA_NOEXCEPT { heap.mpBegin = pBegin; } @@ -1528,11 +1528,11 @@ namespace eastl inline typename basic_string::reference basic_string::front() { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference the trailing 0 char without asserting. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(internalLayout().GetSize() <= 0)) // We assert if the user references the trailing 0 char. + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(internalLayout().GetSize() <= 0)) // We assert if the user references the trailing 0 char. EASTL_FAIL_MSG("basic_string::front -- empty string"); + #else + // We allow the user to reference the trailing 0 char without asserting. #endif return *internalLayout().BeginPtr(); @@ -1543,11 +1543,11 @@ namespace eastl inline typename basic_string::const_reference basic_string::front() const { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference the trailing 0 char without asserting. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(internalLayout().GetSize() <= 0)) // We assert if the user references the trailing 0 char. + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(internalLayout().GetSize() <= 0)) // We assert if the user references the trailing 0 char. EASTL_FAIL_MSG("basic_string::front -- empty string"); + #else + // We allow the user to reference the trailing 0 char without asserting. #endif return *internalLayout().BeginPtr(); @@ -1558,11 +1558,11 @@ namespace eastl inline typename basic_string::reference basic_string::back() { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference the trailing 0 char without asserting. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(internalLayout().GetSize() <= 0)) // We assert if the user references the trailing 0 char. + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(internalLayout().GetSize() <= 0)) // We assert if the user references the trailing 0 char. EASTL_FAIL_MSG("basic_string::back -- empty string"); + #else + // We allow the user to reference the trailing 0 char without asserting. #endif return *(internalLayout().EndPtr() - 1); @@ -1573,11 +1573,11 @@ namespace eastl inline typename basic_string::const_reference basic_string::back() const { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference the trailing 0 char without asserting. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(internalLayout().GetSize() <= 0)) // We assert if the user references the trailing 0 char. + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(internalLayout().GetSize() <= 0)) // We assert if the user references the trailing 0 char. EASTL_FAIL_MSG("basic_string::back -- empty string"); + #else + // We allow the user to reference the trailing 0 char without asserting. #endif return *(internalLayout().EndPtr() - 1); diff --git a/include/EASTL/vector.h b/include/EASTL/vector.h index 85297030..4daec843 100644 --- a/include/EASTL/vector.h +++ b/include/EASTL/vector.h @@ -894,11 +894,12 @@ namespace eastl inline typename vector::reference vector::operator[](size_type n) { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED // We allow the user to use a reference to v[0] of an empty container. But this was merely grandfathered in and ideally we shouldn't allow such access to [0]. - if(EASTL_UNLIKELY((n != 0) && (n >= (static_cast(mpEnd - mpBegin))))) + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(n >= (static_cast(mpEnd - mpBegin)))) EASTL_FAIL_MSG("vector::operator[] -- out of range"); #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(n >= (static_cast(mpEnd - mpBegin)))) + // We allow the user to use a reference to v[0] of an empty container. But this was merely grandfathered in and ideally we shouldn't allow such access to [0]. + if (EASTL_UNLIKELY((n != 0) && (n >= (static_cast(mpEnd - mpBegin))))) EASTL_FAIL_MSG("vector::operator[] -- out of range"); #endif @@ -910,11 +911,12 @@ namespace eastl inline typename vector::const_reference vector::operator[](size_type n) const { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED // We allow the user to use a reference to v[0] of an empty container. But this was merely grandfathered in and ideally we shouldn't allow such access to [0]. - if(EASTL_UNLIKELY((n != 0) && (n >= (static_cast(mpEnd - mpBegin))))) + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY(n >= (static_cast(mpEnd - mpBegin)))) EASTL_FAIL_MSG("vector::operator[] -- out of range"); #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(n >= (static_cast(mpEnd - mpBegin)))) + // We allow the user to use a reference to v[0] of an empty container. But this was merely grandfathered in and ideally we shouldn't allow such access to [0]. + if (EASTL_UNLIKELY((n != 0) && (n >= (static_cast(mpEnd - mpBegin))))) EASTL_FAIL_MSG("vector::operator[] -- out of range"); #endif @@ -926,8 +928,8 @@ namespace eastl inline typename vector::reference vector::at(size_type n) { - // The difference between at() and operator[] is it signals - // the requested position is out of range by throwing an + // The difference between at() and operator[] is it signals + // the requested position is out of range by throwing an // out_of_range exception. #if EASTL_EXCEPTIONS_ENABLED @@ -962,11 +964,11 @@ namespace eastl inline typename vector::reference vector::front() { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(mpEnd <= mpBegin)) // We don't allow the user to reference an empty container. + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY((mpBegin == nullptr) || (mpEnd <= mpBegin))) // We don't allow the user to reference an empty container. EASTL_FAIL_MSG("vector::front -- empty vector"); + #else + // We allow the user to reference an empty container. #endif return *mpBegin; @@ -977,11 +979,11 @@ namespace eastl inline typename vector::const_reference vector::front() const { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(mpEnd <= mpBegin)) // We don't allow the user to reference an empty container. + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY((mpBegin == nullptr) || (mpEnd <= mpBegin))) // We don't allow the user to reference an empty container. EASTL_FAIL_MSG("vector::front -- empty vector"); + #else + // We allow the user to reference an empty container. #endif return *mpBegin; @@ -992,11 +994,11 @@ namespace eastl inline typename vector::reference vector::back() { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(mpEnd <= mpBegin)) // We don't allow the user to reference an empty container. + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY((mpBegin == nullptr) || (mpEnd <= mpBegin))) // We don't allow the user to reference an empty container. EASTL_FAIL_MSG("vector::back -- empty vector"); + #else + // We allow the user to reference an empty container. #endif return *(mpEnd - 1); @@ -1007,11 +1009,11 @@ namespace eastl inline typename vector::const_reference vector::back() const { - #if EASTL_EMPTY_REFERENCE_ASSERT_ENABLED - // We allow the user to reference an empty container. - #elif EASTL_ASSERT_ENABLED - if(EASTL_UNLIKELY(mpEnd <= mpBegin)) // We don't allow the user to reference an empty container. + #if EASTL_ASSERT_ENABLED && EASTL_EMPTY_REFERENCE_ASSERT_ENABLED + if (EASTL_UNLIKELY((mpBegin == nullptr) || (mpEnd <= mpBegin))) // We don't allow the user to reference an empty container. EASTL_FAIL_MSG("vector::back -- empty vector"); + #else + // We allow the user to reference an empty container. #endif return *(mpEnd - 1); diff --git a/test/source/TestSmartPtr.cpp b/test/source/TestSmartPtr.cpp index 031ea8c4..594d569d 100644 --- a/test/source/TestSmartPtr.cpp +++ b/test/source/TestSmartPtr.cpp @@ -1156,6 +1156,15 @@ static int Test_shared_ptr() } + { // Test shared_ptr lambda deleter + auto deleter = [](int*) {}; + eastl::shared_ptr ptr(nullptr, deleter); + + EATEST_VERIFY(!ptr); + EATEST_VERIFY(ptr.get() == nullptr); + } + + { // Test of shared_ptr #if !defined(__GNUC__) || (__GNUC__ >= 3) // If not using old GCC (GCC 2.x is broken)... shared_ptr voidPtr = shared_ptr(new A1); diff --git a/test/source/TestSort.cpp b/test/source/TestSort.cpp index d87b9f09..fffa3b0a 100644 --- a/test/source/TestSort.cpp +++ b/test/source/TestSort.cpp @@ -287,7 +287,7 @@ int TestSort() intArray = intArraySaved; vector buffer(intArray.size()); - merge_sort_buffer(intArray.begin(), intArray.end(), &buffer[0]); + merge_sort_buffer(intArray.begin(), intArray.end(), buffer.data()); EATEST_VERIFY(is_sorted(intArray.begin(), intArray.end())); EATEST_VERIFY(eastl::accumulate(begin(intArraySaved), end(intArraySaved), int64_t(0)) == expectedSum); @@ -305,6 +305,17 @@ int TestSort() } } + // Test insertion_sort() does not invalidate a BidirectionalIterator by doing --BidirectionalIterator.begin() + { + // Test Passes if the Test doesn't crash + eastl::deque deque; + deque.push_back(1); + + insertion_sort(deque.begin(), deque.end()); + + insertion_sort(deque.begin(), deque.end(), eastl::less{}); + } + // TestObject sorting TestObject::Reset();