diff options
author | Andres Noetzli <andres.noetzli@gmail.com> | 2021-04-21 20:25:57 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-22 03:25:57 +0000 |
commit | 3527400d2af35d96a47971db83891b31c47f57ef (patch) | |
tree | 2965a13d498543ff8769a1d916ec839aa916edee /src/context | |
parent | 89620a0d73e7134437a39d742e91de11a08a4962 (diff) |
Allow in-place construction of `CDList` items (#6409)
This commit adds CDList::emplace_back(), which allows users to create
elements in CDList in-place (as opposed to copying the items using
CDList::push_back(). This allows CDList to be used with
std::unique_ptrs, which do not allow copying. Using
CDList::emplace_back() could also be more efficient in certain cases.
Diffstat (limited to 'src/context')
-rw-r--r-- | src/context/cdlist.h | 68 |
1 files changed, 50 insertions, 18 deletions
diff --git a/src/context/cdlist.h b/src/context/cdlist.h index 2bb66eaf2..281901c1c 100644 --- a/src/context/cdlist.h +++ b/src/context/cdlist.h @@ -22,6 +22,7 @@ #include <cstring> #include <iterator> +#include <memory> #include <string> #include "base/check.h" @@ -114,12 +115,23 @@ protected: } CDList& operator=(const CDList& l) = delete; -private: + private: /** - * Reallocate the array with more space. - * Throws bad_alloc if memory allocation fails. + * Reallocate the array with more space. Throws bad_alloc if memory + * allocation fails. Does not perform any action if there is still unused + * allocated space. */ void grow() { + Debug("cdlist") << "grow " << this << " " << getContext()->getLevel() + << ": grow? " << d_size << " " << d_sizeAlloc << std::endl; + if (d_size != d_sizeAlloc) + { + // If there is still unused allocated space + return; + } + Debug("cdlist") << "grow " << this << " " << getContext()->getLevel() + << ": grow!" << std::endl; + if(d_list == NULL) { // Allocate an initial list if one does not yet exist d_sizeAlloc = INITIAL_SIZE; @@ -217,9 +229,7 @@ protected: } } - -public: - + public: /** * Main constructor: d_list starts as NULL, size is 0 */ @@ -265,7 +275,11 @@ public: } /** - * Add an item to the end of the list. + * Add an item to the end of the list. This method uses the copy constructor + * of T, so the type has to support it. As a result, this method cannot be + * used with types that do not have a copy constructor such as + * std::unique_ptr. Use CDList::emplace_back() instead of CDList::push_back() + * to avoid this issue. */ void push_back(const T& data) { Debug("cdlist") << "push_back " << this @@ -273,17 +287,7 @@ public: << ": make-current, " << "d_list == " << d_list << std::endl; makeCurrent(); - - Debug("cdlist") << "push_back " << this - << " " << getContext()->getLevel() - << ": grow? " << d_size - << " " << d_sizeAlloc << std::endl; - if(d_size == d_sizeAlloc) { - Debug("cdlist") << "push_back " << this - << " " << getContext()->getLevel() - << ": grow!" << std::endl; - grow(); - } + grow(); Assert(d_size < d_sizeAlloc); Debug("cdlist") << "push_back " << this @@ -302,6 +306,34 @@ public: } /** + * Construct an item to the end of the list. This method constructs the item + * in-place (similar to std::vector::emplace_back()), so it can be used for + * types that do not have a copy constructor such as std::unique_ptr. + */ + template <typename... Args> + void emplace_back(Args&&... args) + { + Debug("cdlist") << "emplace_back " << this << " " + << getContext()->getLevel() << ": make-current, " + << "d_list == " << d_list << std::endl; + makeCurrent(); + grow(); + Assert(d_size < d_sizeAlloc); + + Debug("cdlist") << "emplace_back " << this << " " + << getContext()->getLevel() << ": construct! at " << d_list + << "[" << d_size << "] == " << &d_list[d_size] << std::endl; + std::allocator_traits<AllocatorT>::construct( + d_allocator, &d_list[d_size], std::forward<Args>(args)...); + Debug("cdlist") << "emplace_back " << this << " " + << getContext()->getLevel() << ": done..." << std::endl; + ++d_size; + Debug("cdlist") << "emplace_back " << this << " " + << getContext()->getLevel() << ": size now " << d_size + << std::endl; + } + + /** * Access to the ith item in the list. */ const T& operator[](size_t i) const { |