aboutsummaryrefslogtreecommitdiff
path: root/include/EASTL/memory.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/EASTL/memory.h')
-rw-r--r--include/EASTL/memory.h1685
1 files changed, 1685 insertions, 0 deletions
diff --git a/include/EASTL/memory.h b/include/EASTL/memory.h
new file mode 100644
index 0000000..cf24b41
--- /dev/null
+++ b/include/EASTL/memory.h
@@ -0,0 +1,1685 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright (c) Electronic Arts Inc. All rights reserved.
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// This file implements the following functions from the C++ standard that
+// are found in the <memory> header:
+//
+// Temporary memory:
+// get_temporary_buffer
+// return_temporary_buffer
+//
+// Utility:
+// late_constructed - Extention to standard functionality.
+//
+// Uninitialized operations:
+// These are the same as the copy, fill, and fill_n algorithms, except that
+// they *construct* the destination with the source values rather than assign
+// the destination with the source values.
+//
+// uninitialized_copy
+// uninitialized_copy_n
+// uninitialized_default_construct
+// uninitialized_default_construct_n
+// uninitialized_move
+// uninitialized_move_if_noexcept - Extention to standard functionality.
+// uninitialized_move_n
+// uninitialized_fill
+// uninitialized_fill_n
+// uninitialized_value_construct
+// uninitialized_value_construct_n
+// uninitialized_default_fill - Extention to standard functionality.
+// uninitialized_default_fill_n - Extention to standard functionality.
+// uninitialized_relocate - Extention to standard functionality.
+// uninitialized_copy_ptr - Extention to standard functionality.
+// uninitialized_move_ptr - Extention to standard functionality.
+// uninitialized_move_ptr_if_noexcept- Extention to standard functionality.
+// uninitialized_fill_ptr - Extention to standard functionality.
+// uninitialized_fill_n_ptr - Extention to standard functionality.
+// uninitialized_copy_fill - Extention to standard functionality.
+// uninitialized_fill_copy - Extention to standard functionality.
+// uninitialized_copy_copy - Extention to standard functionality.
+//
+// In-place destructor helpers:
+// destruct(T*) - Non-standard extension.
+// destruct(first, last) - Non-standard extension.
+// destroy_at(T*)
+// destroy(first, last)
+// destroy_n(first, n)
+//
+// Alignment
+// align
+// align_advance - Extention to standard functionality.
+//
+// Allocator-related
+// uses_allocator
+// allocator_arg_t
+// allocator_arg
+//
+// Pointers
+// pointer_traits
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef EASTL_MEMORY_H
+#define EASTL_MEMORY_H
+
+
+#include <EASTL/internal/config.h>
+#include <EASTL/internal/memory_base.h>
+#include <EASTL/internal/generic_iterator.h>
+#include <EASTL/internal/pair_fwd_decls.h>
+#include <EASTL/internal/functional_base.h>
+#include <EASTL/algorithm.h>
+#include <EASTL/type_traits.h>
+#include <EASTL/allocator.h>
+#include <EASTL/iterator.h>
+#include <EASTL/utility.h>
+#include <EASTL/numeric_limits.h>
+
+EA_DISABLE_ALL_VC_WARNINGS()
+#include <stdlib.h>
+#include <new>
+EA_RESTORE_ALL_VC_WARNINGS()
+
+
+// 4530 - C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
+// 4146 - unary minus operator applied to unsigned type, result still unsigned
+// 4571 - catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught.
+EA_DISABLE_VC_WARNING(4530 4146 4571);
+
+
+#if defined(EA_PRAGMA_ONCE_SUPPORTED)
+ #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.
+#endif
+
+
+namespace eastl
+{
+
+ /// EASTL_TEMP_DEFAULT_NAME
+ ///
+ /// Defines a default container name in the absence of a user-provided name.
+ ///
+ #ifndef EASTL_TEMP_DEFAULT_NAME
+ #define EASTL_TEMP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " temp" // Unless the user overrides something, this is "EASTL temp".
+ #endif
+
+
+ /// get_temporary_buffer
+ ///
+ /// From the C++ standard, section 20.4.3:
+ /// 1 Effects: Obtains a pointer to storage sufficient to store up to n adjacent T objects.
+ /// 2 Returns: A pair containing the buffer's address and capacity (in the units of sizeof(T)),
+ /// or a pair of 0 values if no storage can be obtained.
+ ///
+ /// Note: The return value is space to hold T elements, but no T elements are constructed.
+ ///
+ /// Our implementation here differs slightly in that we have alignment, alignmentOffset, and pName arguments.
+ /// Note that you can use the EASTL_NAME_VAL macro to make names go away in release builds.
+ ///
+ /// Example usage:
+ /// pair<int*, ptrdiff_t> pr = get_temporary_buffer<int>(100, 0, 0, EASTL_NAME_VAL("Temp int array"));
+ /// memset(pr.first, 0, 100 * sizeof(int));
+ /// return_temporary_buffer(pr.first);
+ ///
+ template <typename T>
+ eastl::pair<T*, ptrdiff_t> get_temporary_buffer(ptrdiff_t n, size_t alignment = 1, size_t alignmentOffset = 0, const char* pName = EASTL_TEMP_DEFAULT_NAME)
+ {
+ EASTLAllocatorType allocator(*EASTLAllocatorDefault(), pName);
+ return eastl::pair<T*, ptrdiff_t>(static_cast<T*>(EASTLAllocAligned(allocator, n * sizeof(T), alignment, alignmentOffset)), n);
+ }
+
+
+ /// return_temporary_buffer
+ ///
+ /// From the C++ standard, section 20.4.3:
+ /// 3 Effects: Deallocates the buffer to which p points.
+ /// 4 Requires: The buffer shall have been previously allocated by get_temporary_buffer.
+ ///
+ /// Note: This function merely frees space and does not destruct any T elements.
+ ///
+ /// Example usage:
+ /// pair<int*, ptrdiff_t> pr = get_temporary_buffer<int>(300);
+ /// memset(pr.first, 0, 300 * sizeof(int));
+ /// return_temporary_buffer(pr.first, pr.second);
+ ///
+ template <typename T>
+ void return_temporary_buffer(T* p, ptrdiff_t n = 0)
+ {
+ EASTLAllocatorType& allocator(*EASTLAllocatorDefault());
+ EASTLFree(allocator, p, n * sizeof(T));
+ }
+
+
+
+ /// late_constructed
+ ///
+ /// Implements a smart pointer type which separates the memory allocation of an object from
+ /// the object's construction. The primary use case is to declare a global variable of the
+ /// late_construction type, which allows the memory to be global but the constructor executes
+ /// at some point after main() begins as opposed to before main, which is often dangerous
+ /// for non-trivial types.
+ ///
+ /// The autoConstruct template parameter controls whether the object is automatically default
+ /// constructed upon first reference or must be manually constructed upon the first use of
+ /// operator * or ->. autoConstruct is convenient but it causes * and -> to be slightly slower
+ /// and may result in construction at an inconvenient time.
+ ///
+ /// The autoDestruct template parameter controls whether the object, if constructed, is automatically
+ /// destructed when ~late_constructed() is called or must be manually destructed via a call to
+ /// destruct().
+ ///
+ /// While construction can be automatic or manual, automatic destruction support is always present.
+ /// Thus you aren't required in any case to manually call destruct. However, you may safely manually
+ /// destruct the object at any time before the late_constructed destructor is executed.
+ ///
+ /// You may still use late_constructed after calling destruct(), including calling construct()
+ /// again to reconstruct the instance. destruct returns the late_constructed instance to a
+ /// state equivalent to before construct was called.
+ ///
+ /// Caveat: While late_constructed instances can be declared in global scope and initialize
+ /// prior to main() executing, you cannot otherwise use such globally declared instances prior
+ /// to main with guaranteed behavior unless you can ensure that the late_constructed instance
+ /// is itself constructed prior to your use of it.
+ ///
+ /// Example usage (demonstrating manual-construction):
+ /// late_constructed<Widget, false> gWidget;
+ ///
+ /// void main(){
+ /// gWidget.construct(kScrollbarType, kVertical, "MyScrollbar");
+ /// gWidget->SetValue(15);
+ /// gWidget.destruct();
+ /// }
+ ///
+ /// Example usage (demonstrating auto-construction):
+ /// late_constructed<Widget, true> gWidget;
+ ///
+ /// void main(){
+ /// gWidget->SetValue(15);
+ /// // You may want to call destruct here, but aren't required to do so unless the Widget type requires it.
+ /// }
+ ///
+ template <typename T, bool autoConstruct = true, bool autoDestruct = true>
+ class late_constructed
+ {
+ public:
+ using this_type = late_constructed<T, autoConstruct, autoDestruct>;
+ using value_type = T;
+ using storage_type = eastl::aligned_storage_t<sizeof(value_type), eastl::alignment_of_v<value_type>>;
+
+ late_constructed() EA_NOEXCEPT // In the case of the late_constructed instance being at global scope, we rely on the
+ : mStorage(), mpValue(nullptr) {} // compiler executing this constructor or placing the instance in auto-zeroed-at-startup memory.
+
+ ~late_constructed()
+ {
+ if (autoDestruct && mpValue)
+ (*mpValue).~value_type();
+ }
+
+ template <typename... Args>
+ void construct(Args&&... args)
+ {
+ if(!mpValue)
+ mpValue = new (&mStorage) value_type(eastl::forward<Args>(args)...);
+ }
+
+ bool is_constructed() const EA_NOEXCEPT
+ { return mpValue != nullptr; }
+
+ void destruct()
+ {
+ if(mpValue)
+ {
+ (*mpValue).~value_type();
+ mpValue = nullptr;
+ }
+ }
+
+ value_type& operator*() EA_NOEXCEPT
+ {
+ if(!mpValue)
+ construct();
+
+ EA_ANALYSIS_ASSUME(mpValue);
+ return *mpValue;
+ }
+
+ const value_type& operator*() const EA_NOEXCEPT
+ {
+ if(!mpValue)
+ construct();
+
+ EA_ANALYSIS_ASSUME(mpValue);
+ return *mpValue;
+ }
+
+ value_type* operator->() EA_NOEXCEPT
+ {
+ if(!mpValue)
+ construct();
+ return mpValue;
+ }
+
+ const value_type* operator->() const EA_NOEXCEPT
+ {
+ if(!mpValue)
+ construct();
+ return mpValue;
+ }
+
+ value_type* get() EA_NOEXCEPT
+ {
+ if(!mpValue)
+ construct();
+ return mpValue;
+ }
+
+ const value_type* get() const EA_NOEXCEPT
+ {
+ if(!mpValue)
+ construct();
+ return mpValue;
+ }
+
+ protected:
+ storage_type mStorage; // Declared first because it may have aligment requirements, and it would be more space-efficient if it was first.
+ value_type* mpValue;
+ };
+
+
+ // Specialization that doesn't auto-construct on demand.
+ template <typename T, bool autoDestruct>
+ class late_constructed<T, false, autoDestruct> : public late_constructed<T, true, autoDestruct>
+ {
+ public:
+ typedef late_constructed<T, true, autoDestruct> base_type;
+
+ typename base_type::value_type& operator*() EA_NOEXCEPT
+ { EASTL_ASSERT(base_type::mpValue); return *base_type::mpValue; }
+
+ const typename base_type::value_type& operator*() const EA_NOEXCEPT
+ { EASTL_ASSERT(base_type::mpValue); return *base_type::mpValue; }
+
+ typename base_type::value_type* operator->() EA_NOEXCEPT
+ { EASTL_ASSERT(base_type::mpValue); return base_type::mpValue; }
+
+ const typename base_type::value_type* operator->() const EA_NOEXCEPT
+ { EASTL_ASSERT(base_type::mpValue); return base_type::mpValue; }
+
+ typename base_type::value_type* get() EA_NOEXCEPT
+ { return base_type::mpValue; }
+
+ const typename base_type::value_type* get() const EA_NOEXCEPT
+ { return base_type::mpValue; }
+ };
+
+
+
+ /// raw_storage_iterator
+ ///
+ /// From the C++11 Standard, section 20.6.10 p1
+ /// raw_storage_iterator is provided to enable algorithms to store their results into uninitialized memory.
+ /// The formal template parameter OutputIterator is required to have its operator* return an object for
+ /// which operator& is defined and returns a pointer to T, and is also required to satisfy the requirements
+ /// of an output iterator (24.2.4).
+
+ template <typename OutputIterator, typename T>
+ class raw_storage_iterator : public iterator<EASTL_ITC_NS::output_iterator_tag, void, void, void, void>
+ {
+ protected:
+ OutputIterator mIterator;
+
+ public:
+ explicit raw_storage_iterator(OutputIterator iterator)
+ : mIterator(iterator)
+ {
+ }
+
+ raw_storage_iterator& operator*()
+ {
+ return *this;
+ }
+
+ raw_storage_iterator& operator=(const T& value)
+ {
+ ::new(eastl::addressof(*mIterator)) T(value);
+ return *this;
+ }
+
+ raw_storage_iterator<OutputIterator, T>& operator++()
+ {
+ ++mIterator;
+ return *this;
+ }
+
+ raw_storage_iterator<OutputIterator, T> operator++(int)
+ {
+ raw_storage_iterator<OutputIterator, T> tempIterator = *this;
+ ++mIterator;
+ return tempIterator;
+ }
+ };
+
+
+ /// uninitialized_relocate (formerly named uninitialized_move prior to C++11)
+ ///
+ /// This utility is deprecated in favor of C++11 rvalue move functionality.
+ ///
+ /// uninitialized_relocate takes a constructed sequence of objects and an
+ /// uninitialized destination buffer. In the case of any exception thrown
+ /// while moving the objects, any newly constructed objects are guaranteed
+ /// to be destructed and the input left fully constructed.
+ ///
+ /// In the case where you need to do multiple moves atomically, split the
+ /// calls into uninitialized_relocate_start/abort/commit.
+ ///
+ /// uninitialized_relocate_start can possibly throw an exception. If it does,
+ /// you don't need to do anything. However, if it returns without throwing
+ /// an exception you need to guarantee that either uninitialized_relocate_abort
+ /// or uninitialized_relocate_commit is called.
+ ///
+ /// Both uninitialized_relocate_abort and uninitialize_move_commit are
+ /// guaranteed to not throw C++ exceptions.
+ namespace Internal
+ {
+ template <bool hasTrivialMove, typename iteratorTag>
+ struct uninitialized_relocate_impl
+ {
+ template <typename ForwardIterator, typename ForwardIteratorDest>
+ static ForwardIteratorDest do_move_start(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+
+ #if EASTL_EXCEPTIONS_ENABLED
+ ForwardIteratorDest origDest(dest);
+ try
+ {
+ #endif
+ for(; first != last; ++first, ++dest)
+ ::new((void*)eastl::addressof(*dest)) value_type(*first);
+ #if EASTL_EXCEPTIONS_ENABLED
+ }
+ catch(...)
+ {
+ for(; origDest < dest; ++origDest)
+ (*origDest).~value_type();
+ throw;
+ }
+ #endif
+
+ return dest;
+ }
+
+ template <typename ForwardIterator, typename ForwardIteratorDest>
+ static ForwardIteratorDest do_move_commit(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest) //throw()
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ for(; first != last; ++first, ++dest)
+ (*first).~value_type();
+
+ return dest;
+ }
+
+ template <typename ForwardIterator, typename ForwardIteratorDest>
+ static ForwardIteratorDest do_move_abort(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest) //throw()
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ for(; first != last; ++first, ++dest)
+ (*dest).~value_type();
+ return dest;
+ }
+ };
+
+ template <>
+ struct uninitialized_relocate_impl<true, EASTL_ITC_NS::random_access_iterator_tag>
+ {
+ template <typename T>
+ static T* do_move_start(T* first, T* last, T* dest)
+ {
+ return (T*)memcpy(dest, first, (size_t)((uintptr_t)last - (uintptr_t)first)) + (last - first);
+ }
+
+ template <typename T>
+ static T* do_move_commit(T* first, T* last, T* dest)
+ {
+ return dest + (last - first);
+ }
+
+ template <typename T>
+ static T* do_move_abort(T* first, T* last, T* dest)
+ {
+ return dest + (last - first);
+ }
+ };
+ }
+
+
+ /// uninitialized_relocate_start, uninitialized_relocate_commit, uninitialized_relocate_abort
+ ///
+ /// This utility is deprecated in favor of C++11 rvalue move functionality.
+ ///
+ /// After calling uninitialized_relocate_start, if it doesn't throw an exception,
+ /// both the source and destination iterators point to undefined data. If it
+ /// does throw an exception, the destination remains uninitialized and the source
+ /// is as it was before.
+ ///
+ /// In order to make the iterators valid again you need to call either uninitialized_relocate_abort
+ /// or uninitialized_relocate_commit. The abort call makes the original source
+ /// iterator valid again, and commit makes the destination valid. Both abort
+ /// and commit are guaranteed to not throw C++ exceptions.
+ ///
+ /// Example usage:
+ /// iterator dest2 = uninitialized_relocate_start(first, last, dest);
+ /// try {
+ /// // some code here that might throw an exception
+ /// }
+ /// catch(...)
+ /// {
+ /// uninitialized_relocate_abort(first, last, dest);
+ /// throw;
+ /// }
+ /// uninitialized_relocate_commit(first, last, dest);
+ ///
+ template <typename ForwardIterator, typename ForwardIteratorDest>
+ inline ForwardIteratorDest uninitialized_relocate_start(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::iterator_category IC;
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type_input;
+ typedef typename eastl::iterator_traits<ForwardIteratorDest>::value_type value_type_output;
+
+ const bool bHasTrivialMove = type_and<has_trivial_relocate<value_type_input>::value,
+ is_pointer<ForwardIterator>::value,
+ is_pointer<ForwardIteratorDest>::value,
+ is_same<value_type_input, value_type_output>::value>::value;
+
+ return Internal::uninitialized_relocate_impl<bHasTrivialMove, IC>::do_move_start(first, last, dest);
+ }
+
+ template <typename ForwardIterator, typename ForwardIteratorDest>
+ inline ForwardIteratorDest uninitialized_relocate_commit(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::iterator_category IC;
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type_input;
+ typedef typename eastl::iterator_traits<ForwardIteratorDest>::value_type value_type_output;
+
+ const bool bHasTrivialMove = type_and<has_trivial_relocate<value_type_input>::value,
+ is_pointer<ForwardIterator>::value,
+ is_pointer<ForwardIteratorDest>::value,
+ is_same<value_type_input, value_type_output>::value>::value;
+
+ return Internal::uninitialized_relocate_impl<bHasTrivialMove, IC>::do_move_commit(first, last, dest);
+ }
+
+ template <typename ForwardIterator, typename ForwardIteratorDest>
+ inline ForwardIteratorDest uninitialized_relocate_abort(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::iterator_category IC;
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type_input;
+ typedef typename eastl::iterator_traits<ForwardIteratorDest>::value_type value_type_output;
+
+ const bool bHasTrivialMove = type_and<has_trivial_relocate<value_type_input>::value,
+ is_pointer<ForwardIterator>::value,
+ is_pointer<ForwardIteratorDest>::value,
+ is_same<value_type_input, value_type_output>::value>::value;
+
+ return Internal::uninitialized_relocate_impl<bHasTrivialMove, IC>::do_move_abort(first, last, dest);
+ }
+
+ /// uninitialized_relocate
+ ///
+ /// See above for documentation.
+ ///
+ template <typename ForwardIterator, typename ForwardIteratorDest>
+ inline ForwardIteratorDest uninitialized_relocate(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
+ {
+ ForwardIteratorDest result = uninitialized_relocate_start(first, last, dest);
+ eastl::uninitialized_relocate_commit(first, last, dest);
+
+ return result;
+ }
+
+
+
+
+
+ // uninitialized_copy
+ //
+ namespace Internal
+ {
+ template <typename InputIterator, typename ForwardIterator>
+ inline ForwardIterator uninitialized_copy_impl(InputIterator first, InputIterator last, ForwardIterator dest, true_type)
+ {
+ return eastl::copy(first, last, dest); // The copy() in turn will use memcpy for POD types.
+ }
+
+ template <typename InputIterator, typename ForwardIterator>
+ inline ForwardIterator uninitialized_copy_impl(InputIterator first, InputIterator last, ForwardIterator dest, false_type)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ ForwardIterator currentDest(dest);
+
+ #if EASTL_EXCEPTIONS_ENABLED
+ try
+ {
+ #endif
+ for(; first != last; ++first, ++currentDest)
+ ::new(static_cast<void*>(eastl::addressof(*currentDest))) value_type(*first);
+ #if EASTL_EXCEPTIONS_ENABLED
+ }
+ catch(...)
+ {
+ for(; dest < currentDest; ++dest)
+ (*dest).~value_type();
+ throw;
+ }
+ #endif
+
+ return currentDest;
+ }
+ }
+
+ /// uninitialized_copy
+ ///
+ /// Copies a source range to a destination, copy-constructing the destination with
+ /// the source values (and not *assigning* the destination with the source values).
+ /// Returns the end of the destination range (i.e. dest + (last - first)).
+ ///
+ /// Declaration:
+ /// template <typename InputIterator, typename ForwardIterator>
+ /// ForwardIterator uninitialized_copy(InputIterator sourceFirst, InputIterator sourceLast, ForwardIterator destination);
+ ///
+ /// Example usage:
+ /// SomeClass* pArray = malloc(10 * sizeof(SomeClass));
+ /// uninitialized_copy(pSourceDataBegin, pSourceDataBegin + 10, pArray);
+ ///
+ template <typename InputIterator, typename ForwardIterator>
+ inline ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+
+ // We use is_trivial, which in the C++11 Standard means is_trivially_copyable and is_trivially_default_constructible.
+ return Internal::uninitialized_copy_impl(first, last, result, eastl::is_trivial<value_type>());
+ }
+
+
+ /// uninitialized_copy_n
+ ///
+ /// Copies count elements from a range beginning at first to an uninitialized memory area
+ /// beginning at dest. The elements in the uninitialized area are constructed using copy constructor.
+ /// If an exception is thrown during the initialization, the function has no final effects.
+ ///
+ /// first: Beginning of the range of the elements to copy.
+ /// dest: Beginning of the destination range.
+ /// return value: Iterator of dest type to the element past the last element copied.
+ ///
+ namespace Internal
+ {
+ template <typename InputIterator, typename Count, typename ForwardIterator, typename IteratorTag>
+ struct uninitialized_copy_n_impl
+ {
+ static ForwardIterator impl(InputIterator first, Count n, ForwardIterator dest)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ ForwardIterator currentDest(dest);
+
+ #if EASTL_EXCEPTIONS_ENABLED
+ try
+ {
+ #endif
+ for(; n > 0; --n, ++first, ++currentDest)
+ ::new((void*)(eastl::addressof(*currentDest))) value_type(*first);
+ #if EASTL_EXCEPTIONS_ENABLED
+ }
+ catch(...)
+ {
+ for(; dest < currentDest; ++dest)
+ (*dest).~value_type();
+ throw;
+ }
+ #endif
+
+ return currentDest;
+ }
+ };
+
+ template <typename InputIterator, typename Count, typename ForwardIterator>
+ struct uninitialized_copy_n_impl<InputIterator, Count, ForwardIterator, EASTL_ITC_NS::random_access_iterator_tag>
+ {
+ static inline ForwardIterator impl(InputIterator first, Count n, ForwardIterator dest)
+ {
+ return eastl::uninitialized_copy(first, first + n, dest);
+ }
+ };
+ }
+
+ template<typename InputIterator, typename Count, typename ForwardIterator>
+ inline ForwardIterator uninitialized_copy_n(InputIterator first, Count n, ForwardIterator dest)
+ {
+ typedef typename eastl::iterator_traits<InputIterator>::iterator_category IC;
+ return Internal::uninitialized_copy_n_impl<InputIterator, Count, ForwardIterator, IC>::impl(first, n, dest);
+ }
+
+
+
+ /// uninitialized_copy_ptr
+ ///
+ /// This is a specialization of uninitialized_copy for iterators that are pointers. We use it because
+ /// internally it uses generic_iterator to make pointers act like regular eastl::iterator.
+ ///
+ template <typename First, typename Last, typename Result>
+ inline Result uninitialized_copy_ptr(First first, Last last, Result result)
+ {
+ typedef typename eastl::iterator_traits<generic_iterator<Result, void> >::value_type value_type;
+ const generic_iterator<Result, void> i(Internal::uninitialized_copy_impl(eastl::generic_iterator<First, void>(first), // generic_iterator makes a pointer act like an iterator.
+ eastl::generic_iterator<Last, void>(last),
+ eastl::generic_iterator<Result, void>(result),
+ eastl::is_trivially_copy_assignable<value_type>()));
+ return i.base();
+ }
+
+
+
+ /// uninitialized_move_ptr
+ ///
+ /// This is a specialization of uninitialized_move for iterators that are pointers. We use it because
+ /// internally it uses generic_iterator to make pointers act like regular eastl::iterator.
+ ///
+ namespace Internal
+ {
+ template <typename InputIterator, typename ForwardIterator>
+ inline ForwardIterator uninitialized_move_impl(InputIterator first, InputIterator last, ForwardIterator dest, true_type)
+ {
+ return eastl::copy(first, last, dest); // The copy() in turn will use memcpy for is_trivially_copy_assignable (e.g. POD) types.
+ }
+
+ template <typename InputIterator, typename ForwardIterator>
+ inline ForwardIterator uninitialized_move_impl(InputIterator first, InputIterator last, ForwardIterator dest, false_type)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ ForwardIterator currentDest(dest);
+
+ // We must run a loop over every element and move-construct it at the new location.
+ #if EASTL_EXCEPTIONS_ENABLED
+ try
+ {
+ #endif
+ for(; first != last; ++first, ++currentDest)
+ ::new((void*)eastl::addressof(*currentDest)) value_type(eastl::move(*first)); // If value_type has a move constructor then it will be used here.
+ #if EASTL_EXCEPTIONS_ENABLED
+ }
+ catch(...)
+ {
+ // We have a problem here: If an exception occurs while doing the loop below then we will
+ // have values that were moved from the source to the dest that may need to be moved back
+ // in the catch. What does the C++11 Standard say about this? And what happens if there's an
+ // exception while moving them back? We may want to trace through a conforming C++11 Standard
+ // Library to see what it does and do something similar. Given that rvalue references are
+ // objects that are going away, we may not need to move the values back, though that has the
+ // side effect of a certain kind of lost elements problem.
+ for(; dest < currentDest; ++dest)
+ (*dest).~value_type();
+ throw;
+ }
+ #endif
+
+ return currentDest;
+ }
+ }
+
+ template <typename First, typename Last, typename Result>
+ inline Result uninitialized_move_ptr(First first, Last last, Result dest)
+ {
+ typedef typename eastl::iterator_traits<generic_iterator<Result, void> >::value_type value_type;
+ const generic_iterator<Result, void> i(Internal::uninitialized_move_impl(eastl::generic_iterator<First, void>(first), // generic_iterator makes a pointer act like an iterator.
+ eastl::generic_iterator<Last, void>(last),
+ eastl::generic_iterator<Result, void>(dest),
+ eastl::is_trivially_copy_assignable<value_type>())); // is_trivially_copy_assignable identifies if copy assignment would be as valid as move assignment, which means we have the opportunity to memcpy/memmove optimization.
+ return i.base();
+ }
+
+
+
+
+ /// uninitialized_move
+ ///
+ /// Moves a source range to a destination, move-constructing the destination with
+ /// the source values (and not *assigning* the destination with the source values).
+ /// Returns the end of the destination range (i.e. dest + (last - first)).
+ ///
+ /// uninitialized_move is not part of any current C++ Standard, up to C++14.
+ ///
+ /// Declaration:
+ /// template <typename InputIterator, typename ForwardIterator>
+ /// ForwardIterator uninitialized_move(InputIterator sourceFirst, InputIterator sourceLast, ForwardIterator destination);
+ ///
+ /// Example usage:
+ /// SomeClass* pArray = malloc(10 * sizeof(SomeClass));
+ /// uninitialized_move(pSourceDataBegin, pSourceDataBegin + 10, pArray);
+ ///
+ template <typename InputIterator, typename ForwardIterator>
+ inline ForwardIterator uninitialized_move(InputIterator first, InputIterator last, ForwardIterator dest)
+ {
+ return eastl::uninitialized_copy(eastl::make_move_iterator(first), eastl::make_move_iterator(last), dest);
+ }
+
+
+ /// uninitialized_move_if_noexcept
+ ///
+ /// If the iterated type can be moved without exceptions, move construct the dest with the input. Else copy-construct
+ /// the dest witih the input. If move isn't supported by the compiler, do regular copy.
+ ///
+ template <typename InputIterator, typename ForwardIterator>
+ inline ForwardIterator uninitialized_move_if_noexcept(InputIterator first, InputIterator last, ForwardIterator dest)
+ {
+ return eastl::uninitialized_copy(eastl::make_move_if_noexcept_iterator(first), eastl::make_move_if_noexcept_iterator(last), dest);
+ }
+
+
+ /// uninitialized_move_ptr_if_noexcept
+ ///
+ template <typename First, typename Last, typename Result>
+ inline Result uninitialized_move_ptr_if_noexcept(First first, Last last, Result dest)
+ {
+ #if EASTL_EXCEPTIONS_ENABLED
+ return eastl::uninitialized_move_if_noexcept(first, last, dest);
+ #else
+ return eastl::uninitialized_move_ptr(first, last, dest);
+ #endif
+ }
+
+
+ /// uninitialized_move_n
+ ///
+ /// Moves count elements from a range beginning at first to an uninitialized memory area
+ /// beginning at dest. The elements in the uninitialized area are constructed using copy constructor.
+ /// If an exception is thrown during the initialization, the function has no final effects.
+ ///
+ /// first: Beginning of the range of the elements to move.
+ /// dest: Beginning of the destination range.
+ /// return value: Iterator of dest type to the element past the last element moved.
+ ///
+ template<typename InputIterator, typename Count, typename ForwardIterator>
+ inline ForwardIterator uninitialized_move_n(InputIterator first, Count n, ForwardIterator dest)
+ {
+ return eastl::uninitialized_copy_n(eastl::make_move_iterator(first), n, dest);
+ }
+
+ // Disable warning C4345 - behavior change: an object of POD type constructed with an initializer of the form ()
+ // will be default-initialized.
+ // This is the behavior we intend below.
+ EA_DISABLE_VC_WARNING(4345)
+ /// uninitialized_default_fill
+ ///
+ /// Default-constructs the elements in the destination range.
+ /// Returns void. It wouldn't be useful to return the end of the destination range,
+ /// as that is the same as the 'last' input parameter.
+ ///
+ /// Declaration:
+ /// template <typename ForwardIterator, typename T>
+ /// void uninitialized_default_fill(ForwardIterator destinationFirst, ForwardIterator destinationLast);
+ ///
+ template <typename ForwardIterator>
+ inline void uninitialized_default_fill(ForwardIterator first, ForwardIterator last)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ ForwardIterator currentDest(first);
+
+ #if EASTL_EXCEPTIONS_ENABLED
+ try
+ {
+ #endif
+ for (; currentDest != last; ++currentDest)
+ ::new (eastl::addressof(*currentDest)) value_type();
+ #if EASTL_EXCEPTIONS_ENABLED
+ }
+ catch (...)
+ {
+ for (; first < currentDest; ++first)
+ (*first).~value_type();
+ throw;
+ }
+ #endif
+ }
+
+ /// uninitialized_default_fill_n
+ ///
+ /// Default-constructs the range of [first, first + n).
+ /// Returns void as per the C++ standard, though returning the end input iterator
+ /// value may be of use.
+ ///
+ /// Declaration:
+ /// template <typename ForwardIterator, typename Count, typename T>
+ /// void uninitialized_default_fill_n(ForwardIterator destination, Count n);
+ ///
+ namespace Internal
+ {
+ template <typename ForwardIterator, typename Count>
+ inline void uninitialized_default_fill_n_impl(ForwardIterator first, Count n, false_type)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ ForwardIterator currentDest(first);
+
+ #if EASTL_EXCEPTIONS_ENABLED
+ try
+ {
+ #endif
+ for (; n > 0; --n, ++currentDest)
+ ::new (eastl::addressof(*currentDest)) value_type();
+ #if EASTL_EXCEPTIONS_ENABLED
+ }
+ catch (...)
+ {
+ for (; first < currentDest; ++first)
+ (*first).~value_type();
+ throw;
+ }
+ #endif
+ }
+
+ template <typename ForwardIterator, typename Count>
+ inline void uninitialized_default_fill_n_impl(ForwardIterator first, Count n, true_type)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ memset(first, 0, sizeof(value_type) * n);
+ }
+ }
+
+ template <typename ForwardIterator, typename Count>
+ inline void uninitialized_default_fill_n(ForwardIterator first, Count n)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ Internal::uninitialized_default_fill_n_impl(first, n, is_scalar<value_type>());
+ }
+ EA_RESTORE_VC_WARNING()
+
+ /// uninitialized_default_construct
+ ///
+ /// Constructs objects in the uninitialized storage designated by the range [first, last) by default-initialization.
+ ///
+ /// Default-initialization:
+ /// If T is a class, the default constructor is called; otherwise, no initialization is done, resulting in
+ /// indeterminate values.
+ ///
+ /// http://en.cppreference.com/w/cpp/memory/uninitialized_default_construct
+ ///
+ template <typename ForwardIterator>
+ inline void uninitialized_default_construct(ForwardIterator first, ForwardIterator last)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ ForwardIterator currentDest(first);
+
+ #if EASTL_EXCEPTIONS_ENABLED
+ try
+ {
+ #endif
+ for (; currentDest != last; ++currentDest)
+ ::new (eastl::addressof(*currentDest)) value_type;
+ #if EASTL_EXCEPTIONS_ENABLED
+ }
+ catch (...)
+ {
+ for (; first < currentDest; ++first)
+ (*first).~value_type();
+ throw;
+ }
+ #endif
+ }
+
+ /// uninitialized_default_construct_n
+ ///
+ /// Constructs n objects in the uninitialized storage starting at first by default-initialization.
+ ///
+ /// http://en.cppreference.com/w/cpp/memory/uninitialized_default_construct_n
+ ///
+ template <typename ForwardIterator, typename Count>
+ inline ForwardIterator uninitialized_default_construct_n(ForwardIterator first, Count n)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ ForwardIterator currentDest(first);
+
+ #if EASTL_EXCEPTIONS_ENABLED
+ try
+ {
+ #endif
+ for (; n > 0; --n, ++currentDest)
+ ::new (eastl::addressof(*currentDest)) value_type;
+ return currentDest;
+ #if EASTL_EXCEPTIONS_ENABLED
+ }
+ catch (...)
+ {
+ for (; first < currentDest; ++first)
+ (*first).~value_type();
+ throw;
+ }
+ #endif
+ }
+
+ /// uninitialized_fill
+ ///
+ /// Copy-constructs the elements in the destination range with the given input value.
+ /// Returns void. It wouldn't be useful to return the end of the destination range,
+ /// as that is the same as the 'last' input parameter.
+ ///
+ /// Declaration:
+ /// template <typename ForwardIterator, typename T>
+ /// void uninitialized_fill(ForwardIterator destinationFirst, ForwardIterator destinationLast, const T& value);
+ ///
+ namespace Internal
+ {
+ template <typename ForwardIterator, typename T>
+ inline void uninitialized_fill_impl(ForwardIterator first, ForwardIterator last, const T& value, true_type)
+ {
+ eastl::fill(first, last, value);
+ }
+
+ template <typename ForwardIterator, typename T>
+ void uninitialized_fill_impl(ForwardIterator first, ForwardIterator last, const T& value, false_type)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ ForwardIterator currentDest(first);
+
+ #if EASTL_EXCEPTIONS_ENABLED
+ try
+ {
+ #endif
+ for(; currentDest != last; ++currentDest)
+ ::new((void*)eastl::addressof(*currentDest)) value_type(value);
+ #if EASTL_EXCEPTIONS_ENABLED
+ }
+ catch(...)
+ {
+ for(; first < currentDest; ++first)
+ (*first).~value_type();
+ throw;
+ }
+ #endif
+ }
+ }
+
+ template <typename ForwardIterator, typename T>
+ inline void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& value)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ Internal::uninitialized_fill_impl(first, last, value, eastl::is_trivially_copy_assignable<value_type>());
+ }
+
+ /// uninitialized_value_construct
+ ///
+ /// Constructs objects in the uninitialized storage range [first, last) by value-initialization.
+ ///
+ /// Value-Initialization:
+ /// If T is a class, the object is default-initialized (after being zero-initialized if T's default
+ /// constructor is not user-provided/deleted); otherwise, the object is zero-initialized.
+ ///
+ /// http://en.cppreference.com/w/cpp/memory/uninitialized_value_construct
+ ///
+ template <class ForwardIterator>
+ void uninitialized_value_construct(ForwardIterator first, ForwardIterator last)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ ForwardIterator currentDest(first);
+
+ #if EASTL_EXCEPTIONS_ENABLED
+ try
+ {
+ #endif
+ for (; currentDest != last; ++currentDest)
+ ::new (eastl::addressof(*currentDest)) value_type();
+ #if EASTL_EXCEPTIONS_ENABLED
+ }
+ catch (...)
+ {
+ for (; first < currentDest; ++first)
+ (*first).~value_type();
+ throw;
+ }
+ #endif
+ }
+
+ /// uninitialized_value_construct_n
+ ///
+ /// Constructs n objects in the uninitialized storage starting at first by value-initialization.
+ ///
+ /// Value-Initialization:
+ /// If T is a class, the object is default-initialized (after being zero-initialized if T's default
+ /// constructor is not user-provided/deleted); otherwise, the object is zero-initialized.
+ ///
+ /// http://en.cppreference.com/w/cpp/memory/uninitialized_value_construct_n
+ ///
+ template <class ForwardIterator, class Count>
+ ForwardIterator uninitialized_value_construct_n(ForwardIterator first, Count n)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ ForwardIterator currentDest(first);
+
+ #if EASTL_EXCEPTIONS_ENABLED
+ try
+ {
+ #endif
+ for (; n > 0; --n, ++currentDest)
+ ::new (eastl::addressof(*currentDest)) value_type();
+ return currentDest;
+ #if EASTL_EXCEPTIONS_ENABLED
+ }
+ catch (...)
+ {
+ for (; first < currentDest; ++first)
+ (*first).~value_type();
+ throw;
+ }
+ #endif
+ }
+
+ /// uninitialized_fill_ptr
+ ///
+ /// This is a specialization of uninitialized_fill for iterators that are pointers.
+ /// It exists so that we can declare a value_type for the iterator, which you
+ /// can't do with a pointer by itself.
+ ///
+ template <typename T>
+ inline void uninitialized_fill_ptr(T* first, T* last, const T& value)
+ {
+ typedef typename eastl::iterator_traits<eastl::generic_iterator<T*, void> >::value_type value_type;
+ Internal::uninitialized_fill_impl(eastl::generic_iterator<T*, void>(first),
+ eastl::generic_iterator<T*, void>(last), value,
+ eastl::is_trivially_copy_assignable<value_type>());
+ }
+
+ /// uninitialized_fill_n
+ ///
+ /// Copy-constructs the range of [first, first + n) with the given input value.
+ /// Returns void as per the C++ standard, though returning the end input iterator
+ /// value may be of use.
+ ///
+ /// Declaration:
+ /// template <typename ForwardIterator, typename Count, typename T>
+ /// void uninitialized_fill_n(ForwardIterator destination, Count n, const T& value);
+ ///
+ namespace Internal
+ {
+ template <typename ForwardIterator, typename Count, typename T>
+ inline void uninitialized_fill_n_impl(ForwardIterator first, Count n, const T& value, true_type)
+ {
+ eastl::fill_n(first, n, value);
+ }
+
+ template <typename ForwardIterator, typename Count, typename T>
+ void uninitialized_fill_n_impl(ForwardIterator first, Count n, const T& value, false_type)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ ForwardIterator currentDest(first);
+
+ #if EASTL_EXCEPTIONS_ENABLED
+ try
+ {
+ #endif
+ for(; n > 0; --n, ++currentDest)
+ ::new((void*)eastl::addressof(*currentDest)) value_type(value);
+ #if EASTL_EXCEPTIONS_ENABLED
+ }
+ catch(...)
+ {
+ for(; first < currentDest; ++first)
+ (*first).~value_type();
+ throw;
+ }
+ #endif
+ }
+ }
+
+ template <typename ForwardIterator, typename Count, typename T>
+ inline void uninitialized_fill_n(ForwardIterator first, Count n, const T& value)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ Internal::uninitialized_fill_n_impl(first, n, value, eastl::is_trivially_copy_assignable<value_type>());
+ }
+
+
+
+ /// uninitialized_fill_n_ptr
+ ///
+ /// This is a specialization of uninitialized_fill_n for iterators that are pointers.
+ /// It exists so that we can declare a value_type for the iterator, which you
+ /// can't do with a pointer by itself.
+ ///
+ template <typename T, typename Count>
+ inline void uninitialized_fill_n_ptr(T* first, Count n, const T& value)
+ {
+ typedef typename eastl::iterator_traits<generic_iterator<T*, void> >::value_type value_type;
+ Internal::uninitialized_fill_n_impl(eastl::generic_iterator<T*, void>(first), n, value, eastl::is_trivially_copy_assignable<value_type>());
+ }
+
+
+
+
+ /// uninitialized_copy_fill
+ ///
+ /// Copies [first1, last1) into [first2, first2 + (last1 - first1)) then
+ /// fills [first2 + (last1 - first1), last2) with value.
+ ///
+ template <typename InputIterator, typename ForwardIterator, typename T>
+ inline void uninitialized_copy_fill(InputIterator first1, InputIterator last1,
+ ForwardIterator first2, ForwardIterator last2, const T& value)
+ {
+ const ForwardIterator mid(eastl::uninitialized_copy(first1, last1, first2));
+
+ #if EASTL_EXCEPTIONS_ENABLED
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ try
+ {
+ #endif
+ eastl::uninitialized_fill(mid, last2, value);
+ #if EASTL_EXCEPTIONS_ENABLED
+ }
+ catch(...)
+ {
+ for(; first2 < mid; ++first2)
+ (*first2).~value_type();
+ throw;
+ }
+ #endif
+ }
+
+
+ /// uninitialized_move_fill
+ ///
+ /// Moves [first1, last1) into [first2, first2 + (last1 - first1)) then
+ /// fills [first2 + (last1 - first1), last2) with value.
+ ///
+ template <typename InputIterator, typename ForwardIterator, typename T>
+ inline void uninitialized_move_fill(InputIterator first1, InputIterator last1,
+ ForwardIterator first2, ForwardIterator last2, const T& value)
+ {
+ const ForwardIterator mid(eastl::uninitialized_move(first1, last1, first2));
+
+ #if EASTL_EXCEPTIONS_ENABLED
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ try
+ {
+ #endif
+ eastl::uninitialized_fill(mid, last2, value);
+ #if EASTL_EXCEPTIONS_ENABLED
+ }
+ catch(...)
+ {
+ for(; first2 < mid; ++first2)
+ (*first2).~value_type();
+ throw;
+ }
+ #endif
+ }
+
+
+
+
+
+ /// uninitialized_fill_copy
+ ///
+ /// Fills [result, mid) with value then copies [first, last) into [mid, mid + (last - first)).
+ ///
+ template <typename ForwardIterator, typename T, typename InputIterator>
+ inline ForwardIterator
+ uninitialized_fill_copy(ForwardIterator result, ForwardIterator mid, const T& value, InputIterator first, InputIterator last)
+ {
+ eastl::uninitialized_fill(result, mid, value);
+
+ #if EASTL_EXCEPTIONS_ENABLED
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ try
+ {
+ #endif
+ return eastl::uninitialized_copy(first, last, mid);
+ #if EASTL_EXCEPTIONS_ENABLED
+ }
+ catch(...)
+ {
+ for(; result < mid; ++result)
+ (*result).~value_type();
+ throw;
+ }
+ #endif
+ }
+
+
+ /// uninitialized_fill_move
+ ///
+ /// Fills [result, mid) with value then copies [first, last) into [mid, mid + (last - first)).
+ ///
+ template <typename ForwardIterator, typename T, typename InputIterator>
+ inline ForwardIterator
+ uninitialized_fill_move(ForwardIterator result, ForwardIterator mid, const T& value, InputIterator first, InputIterator last)
+ {
+ eastl::uninitialized_fill(result, mid, value);
+
+ #if EASTL_EXCEPTIONS_ENABLED
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ try
+ {
+ #endif
+ return eastl::uninitialized_move(first, last, mid);
+ #if EASTL_EXCEPTIONS_ENABLED
+ }
+ catch(...)
+ {
+ for(; result < mid; ++result)
+ (*result).~value_type();
+ throw;
+ }
+ #endif
+ }
+
+
+
+ /// uninitialized_copy_copy
+ ///
+ /// Copies [first1, last1) into [result, result + (last1 - first1)) then
+ /// copies [first2, last2) into [result, result + (last1 - first1) + (last2 - first2)).
+ ///
+ template <typename InputIterator1, typename InputIterator2, typename ForwardIterator>
+ inline ForwardIterator
+ uninitialized_copy_copy(InputIterator1 first1, InputIterator1 last1,
+ InputIterator2 first2, InputIterator2 last2,
+ ForwardIterator result)
+ {
+ const ForwardIterator mid(eastl::uninitialized_copy(first1, last1, result));
+
+ #if EASTL_EXCEPTIONS_ENABLED
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ try
+ {
+ #endif
+ return eastl::uninitialized_copy(first2, last2, mid);
+ #if EASTL_EXCEPTIONS_ENABLED
+ }
+ catch(...)
+ {
+ for(; result < mid; ++result)
+ (*result).~value_type();
+ throw;
+ }
+ #endif
+ }
+
+
+
+ /// destruct
+ ///
+ /// Calls the destructor of a given object.
+ ///
+ /// Note that we don't have a specialized version of this for objects
+ /// with trivial destructors, such as integers. This is because the
+ /// compiler can already see in our version here that the destructor
+ /// is a no-op.
+ ///
+ template <typename T>
+ inline void destruct(T* p)
+ {
+ // https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(C4100)&rd=true
+ // "C4100 can also be issued when code calls a destructor on a otherwise unreferenced parameter
+ // of primitive type. This is a limitation of the Visual C++ compiler."
+ EA_UNUSED(p);
+ p->~T();
+ }
+
+
+
+ // destruct(first, last)
+ //
+ template <typename ForwardIterator>
+ inline void destruct_impl(ForwardIterator /*first*/, ForwardIterator /*last*/, true_type) // true means the type has a trivial destructor.
+ {
+ // Empty. The type has a trivial destructor.
+ }
+
+ template <typename ForwardIterator>
+ inline void destruct_impl(ForwardIterator first, ForwardIterator last, false_type) // false means the type has a significant destructor.
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+
+ for(; first != last; ++first)
+ (*first).~value_type();
+ }
+
+ /// destruct
+ ///
+ /// Calls the destructor on a range of objects.
+ ///
+ /// We have a specialization for objects with trivial destructors, such as
+ /// PODs. In this specialization the destruction of the range is a no-op.
+ ///
+ template <typename ForwardIterator>
+ inline void destruct(ForwardIterator first, ForwardIterator last)
+ {
+ typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
+ destruct_impl(first, last, eastl::has_trivial_destructor<value_type>());
+ }
+
+
+ /// destroy_at
+ ///
+ /// Calls the destructor of a given object.
+ ///
+ /// Note that we don't have a specialized version of this for objects
+ /// with trivial destructors, such as integers. This is because the
+ /// compiler can already see in our version here that the destructor
+ /// is a no-op.
+ ///
+ /// This is the same as eastl::destruct but we included for C++17 compliance.
+ ///
+ /// http://en.cppreference.com/w/cpp/memory/destroy_at
+ ///
+ template <typename T>
+ inline void destroy_at(T* p)
+ {
+ EA_UNUSED(p);
+ p->~T();
+ }
+
+
+ /// destroy
+ ///
+ /// Calls the destructor on a range of objects.
+ ///
+ /// http://en.cppreference.com/w/cpp/memory/destroy
+ ///
+ template <typename ForwardIterator>
+ inline void destroy(ForwardIterator first, ForwardIterator last)
+ {
+ for (; first != last; ++first)
+ eastl::destroy_at(eastl::addressof(*first));
+ }
+
+
+ /// destroy_n
+ ///
+ /// Calls the destructor on the n objects in the range.
+ ///
+ /// http://en.cppreference.com/w/cpp/memory/destroy_n
+ ///
+ template <typename ForwardIterator, typename Size>
+ ForwardIterator destroy_n(ForwardIterator first, Size n)
+ {
+ for (; n > 0; ++first, --n)
+ eastl::destroy_at(eastl::addressof(*first));
+
+ return first;
+ }
+
+
+ /// align
+ ///
+ /// Same as C++11 std::align. http://en.cppreference.com/w/cpp/memory/align
+ /// If it is possible to fit size bytes of storage aligned by alignment into the buffer pointed to by
+ /// ptr with length space, the function updates ptr to point to the first possible address of such storage,
+ /// decreases space by the number of bytes used for alignment, and returns the new ptr value. Otherwise,
+ /// the function returns NULL and leaves ptr and space unmodified.
+ ///
+ /// Example usage:
+ /// char buffer[512];
+ /// size_t space = sizeof(buffer);
+ /// void* p = buffer;
+ /// void* p1 = eastl::align(16, 3, p, space); p = (char*)p + 3; space -= 3;
+ /// void* p2 = eastl::align(32, 78, p, space); p = (char*)p + 78; space -= 78;
+ /// void* p3 = eastl::align(64, 9, p, space); p = (char*)p + 9; space -= 9;
+
+ inline void* align(size_t alignment, size_t size, void*& ptr, size_t& space)
+ {
+ if(space >= size)
+ {
+ char* ptrAligned = (char*)(((size_t)ptr + (alignment - 1)) & -alignment);
+ size_t offset = (size_t)(ptrAligned - (char*)ptr);
+
+ if((space - size) >= offset) // Have to implement this in terms of subtraction instead of addition in order to handle possible overflow.
+ {
+ ptr = ptrAligned;
+ space -= offset;
+
+ return ptrAligned;
+ }
+ }
+
+ return NULL;
+ }
+
+
+ /// align_advance
+ ///
+ /// Same as align except ptr and space can be adjusted to reflect remaining space.
+ /// Not present in the C++ Standard.
+ /// Note that the example code here is similar to align but simpler.
+ ///
+ /// Example usage:
+ /// char buffer[512];
+ /// size_t space = sizeof(buffer);
+ /// void* p = buffer;
+ /// void* p1 = eastl::align_advance(16, 3, p, space, &p, &space); // p is advanced and space reduced accordingly.
+ /// void* p2 = eastl::align_advance(32, 78, p, space, &p, &space);
+ /// void* p3 = eastl::align_advance(64, 9, p, space, &p, &space);
+ /// void* p4 = eastl::align_advance(16, 33, p, space);
+
+ inline void* align_advance(size_t alignment, size_t size, void* ptr, size_t space, void** ptrAdvanced = NULL, size_t* spaceReduced = NULL)
+ {
+ if(space >= size)
+ {
+ char* ptrAligned = (char*)(((size_t)ptr + (alignment - 1)) & -alignment);
+ size_t offset = (size_t)(ptrAligned - (char*)ptr);
+
+ if((space - size) >= offset) // Have to implement this in terms of subtraction instead of addition in order to handle possible overflow.
+ {
+ if(ptrAdvanced)
+ *ptrAdvanced = (ptrAligned + size);
+ if(spaceReduced)
+ *spaceReduced = (space - (offset + size));
+
+ return ptrAligned;
+ }
+ }
+
+ return NULL;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////
+ // uses_allocator
+ //
+ // Determines if the class T has an allocator_type member typedef
+ // which Allocator is convertible to.
+ //
+ // http://en.cppreference.com/w/cpp/memory/uses_allocator
+ //
+ // A program may specialize this template to derive from true_type for a
+ // user-defined type T that does not have a nested allocator_type but
+ // nonetheless can be constructed with an allocator where either:
+ // - the first argument of a constructor has type allocator_arg_t and
+ // the second argument has type Allocator.
+ // or
+ // - the last argument of a constructor has type Allocator.
+ //
+ // Example behavilor:
+ // uses_allocator<vector>::value => true
+ // uses_allocator<int>::value => false
+ //
+ // This is useful for writing generic code for containers when you can't
+ // know ahead of time that the container has an allocator_type.
+ ///////////////////////////////////////////////////////////////////////
+
+ template <typename T>
+ struct has_allocator_type_helper
+ {
+ private:
+ template <typename>
+ static eastl::no_type test(...);
+
+ template <typename U>
+ static eastl::yes_type test(typename U::allocator_type* = NULL);
+
+ public:
+ static const bool value = sizeof(test<T>(NULL)) == sizeof(eastl::yes_type);
+ };
+
+
+ template <typename T, typename Allocator, bool = has_allocator_type_helper<T>::value>
+ struct uses_allocator_impl
+ : public integral_constant<bool, eastl::is_convertible<Allocator, typename T::allocator_type>::value>
+ {
+ };
+
+ template <typename T, typename Allocator>
+ struct uses_allocator_impl<T, Allocator, false>
+ : public eastl::false_type
+ {
+ };
+
+ template <typename T, typename Allocator>
+ struct uses_allocator
+ : public uses_allocator_impl<T, Allocator>{ };
+
+
+
+
+
+ ///////////////////////////////////////////////////////////////////////
+ // pointer_traits
+ //
+ // C++11 Standard section 20.6.3
+ // Provides information about a pointer type, mostly for the purpose
+ // of handling the case where the pointer type isn't a built-in T* but
+ // rather is a class that acts like a pointer.
+ //
+ // A user-defined Pointer has the following properties, by example:
+ // template <class T, class... MoreArgs>
+ // struct Pointer
+ // {
+ // typedef Pointer pointer; // required for use by pointer_traits.
+ // typedef T1 element_type; // optional for use by pointer_traits.
+ // typedef T2 difference_type; // optional for use by pointer_traits.
+ //
+ // template <class Other>
+ // using rebind = typename Ptr<Other, MoreArgs...>; // optional for use by pointer_traits.
+ //
+ // static pointer pointer_to(element_type& obj); // required for use by pointer_traits.
+ // };
+ //
+ //
+ // Example usage:
+ // template <typename Pointer>
+ // typename pointer_traits::element_type& GetElementPointedTo(Pointer p)
+ // { return *p; }
+ //
+ ///////////////////////////////////////////////////////////////////////
+
+ namespace Internal
+ {
+ // pointer_element_type
+ template <typename Pointer>
+ struct has_element_type // has_element_type<T>::value is true if T has an element_type member typedef.
+ {
+ private:
+ template <typename U> static eastl::no_type test(...);
+ template <typename U> static eastl::yes_type test(typename U::element_type* = 0);
+ public:
+ static const bool value = sizeof(test<Pointer>(0)) == sizeof(eastl::yes_type);
+ };
+
+ template <typename Pointer, bool = has_element_type<Pointer>::value>
+ struct pointer_element_type
+ {
+ using type = Pointer;
+ };
+
+ template <typename Pointer>
+ struct pointer_element_type<Pointer, true>
+ { typedef typename Pointer::element_type type; };
+
+ template <template <typename, typename...> class Pointer, typename T, typename... Args>
+ struct pointer_element_type<Pointer<T, Args...>, false>
+ { typedef T type; };
+
+
+ // pointer_difference_type
+ template <typename Pointer>
+ struct has_difference_type // has_difference_type<T>::value is true if T has an difference_type member typedef.
+ {
+ private:
+ template <typename U> static eastl::no_type test(...);
+ template <typename U> static eastl::yes_type test(typename U::difference_type* = 0);
+ public:
+ static const bool value = sizeof((test<Pointer>(0))) == sizeof(eastl::yes_type);
+ };
+
+ template <typename Pointer, bool = has_difference_type<Pointer>::value>
+ struct pointer_difference_type
+ { typedef typename Pointer::difference_type type; };
+
+ template <typename Pointer>
+ struct pointer_difference_type<Pointer, false>
+ { typedef ptrdiff_t type; };
+
+
+ // pointer_rebind
+ // The following isn't correct, as it is unilaterally requiring that Pointer typedef its
+ // own rebind. We can fix this if needed to make it optional (in which case it would return
+ // its own type), but we don't currently use rebind in EASTL (as we have a different allocator
+ // system than the C++ Standard Library has) and this is currently moot.
+ template <typename Pointer, typename U>
+ struct pointer_rebind
+ {
+ typedef typename Pointer::template rebind<U> type;
+ };
+
+
+ } // namespace Internal
+
+
+ template <typename Pointer>
+ struct pointer_traits
+ {
+ typedef Pointer pointer;
+ typedef typename Internal::pointer_element_type<pointer>::type element_type;
+ typedef typename Internal::pointer_difference_type<pointer>::type difference_type;
+
+ #if defined(EA_COMPILER_NO_TEMPLATE_ALIASES)
+ template <typename U>
+ struct rebind { typedef typename Internal::pointer_rebind<pointer, U>::type other; };
+ #else
+ template <typename U>
+ using rebind = typename Internal::pointer_rebind<pointer, U>::type;
+ #endif
+
+ public:
+ static pointer pointer_to(typename eastl::conditional<eastl::is_void<element_type>::value, void, element_type>::type& r) // 20.6.3.2: if element_type is (possibly cv-qualified) void, the type of r is unspecified; otherwise, it is T&.
+ { return pointer::pointer_to(r); } // The C++11 Standard requires that Pointer provides a static pointer_to function.
+ };
+
+
+ template <typename T>
+ struct pointer_traits<T*>
+ {
+ typedef T* pointer;
+ typedef T element_type;
+ typedef ptrdiff_t difference_type;
+
+ #if defined(EA_COMPILER_NO_TEMPLATE_ALIASES)
+ template <typename U>
+ struct rebind { typedef U* other; };
+ #else
+ template <typename U>
+ using rebind = U*;
+ #endif
+
+ public:
+ static pointer pointer_to(typename eastl::conditional<eastl::is_void<element_type>::value, void, element_type>::type& r) EA_NOEXCEPT
+ { return eastl::addressof(r); } // 20.6.3.2: if element_type is (possibly cv-qualified) void, the type of r is unspecified; otherwise, it is T&.
+ };
+
+} // namespace eastl
+
+
+EA_RESTORE_VC_WARNING();
+
+
+#endif // Header include guard