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.h1726
1 files changed, 0 insertions, 1726 deletions
diff --git a/include/EASTL/memory.h b/include/EASTL/memory.h
deleted file mode 100644
index ab2798f..0000000
--- a/include/EASTL/memory.h
+++ /dev/null
@@ -1,1726 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// 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)
- {
- if (EASTL_UNLIKELY(first == last))
- return 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)
- {
- if (EASTL_UNLIKELY(n == 0))
- return;
-
- 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&.
- };
-
- ///////////////////////////////////////////////////////////////////////
- // to_address
- //
- // Helper that call the customization point in pointer_traits<T>::to_address for retrieving the address of a pointer.
- // This is useful if you are using fancy-pointers.
- ///////////////////////////////////////////////////////////////////////
-
- namespace Internal
- {
- template <class T>
- using detect_pointer_traits_to_address = decltype(eastl::pointer_traits<T>::to_address(eastl::declval<const T&>()));
-
- template <class T>
- using result_detect_pointer_traits_to_address = eastl::is_detected<detect_pointer_traits_to_address, T>;
- }
-
- template<class T>
- EA_CPP14_CONSTEXPR T* to_address(T* p) noexcept
- {
- static_assert(!eastl::is_function<T>::value, "Cannot call to_address with a function pointer. C++20 20.2.4.1 - Pointer conversion.");
- return p;
- }
-
- template <class Ptr, typename eastl::enable_if<Internal::result_detect_pointer_traits_to_address<Ptr>::value, int>::type = 0>
- EA_CPP14_CONSTEXPR auto to_address(const Ptr& ptr) noexcept -> decltype(eastl::pointer_traits<Ptr>::to_address(ptr))
- {
- return eastl::pointer_traits<Ptr>::to_address(ptr);
- }
-
- template <class Ptr, typename eastl::enable_if<!Internal::result_detect_pointer_traits_to_address<Ptr>::value, int>::type = 0>
- EA_CPP14_CONSTEXPR auto to_address(const Ptr& ptr) noexcept -> decltype(to_address(ptr.operator->()))
- {
- return to_address(ptr.operator->());
- }
-
-} // namespace eastl
-
-
-EA_RESTORE_VC_WARNING();
-
-
-#endif // Header include guard