diff options
author | Ben Smith <binjimin@gmail.com> | 2017-09-13 18:45:29 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-13 18:45:29 -0700 |
commit | 7a0bf623e2b69621fa45f2d194c9dd6233086203 (patch) | |
tree | ec6f782dba8b8b1d8d3dd5c201097056a5f33c3c /src/circular-array.h | |
parent | e592d8d95a2d1a21d04e8311ef1aaee07be26e62 (diff) | |
download | wabt-7a0bf623e2b69621fa45f2d194c9dd6233086203.tar.gz wabt-7a0bf623e2b69621fa45f2d194c9dd6233086203.tar.bz2 wabt-7a0bf623e2b69621fa45f2d194c9dd6233086203.zip |
Support non-POD types in CircularArray (#625)
This is necessary if we want to allow Token to have a destructor.
Also add some tests for the API.
Diffstat (limited to 'src/circular-array.h')
-rw-r--r-- | src/circular-array.h | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/src/circular-array.h b/src/circular-array.h index 265410e8..c14721fd 100644 --- a/src/circular-array.h +++ b/src/circular-array.h @@ -25,8 +25,6 @@ namespace wabt { // TODO(karlschimpf) Complete the API -// TODO(karlschimpf) Apply constructors/destructors on base type T -// as collection size changes (if not POD). // Note: Capacity must be a power of 2. template<class T, size_t kCapacity> class CircularArray { @@ -37,11 +35,21 @@ class CircularArray { typedef size_t size_type; typedef ptrdiff_t difference_type; - CircularArray() : size_(0), front_(0), mask_(kCapacity - 1) { + CircularArray() { static_assert(kCapacity && ((kCapacity & (kCapacity - 1)) == 0), "Capacity must be a power of 2."); } + CircularArray(const CircularArray&) = default; + CircularArray& operator =(const CircularArray&) = default; + + CircularArray(CircularArray&&) = default; + CircularArray& operator =(CircularArray&&) = default; + + ~CircularArray() { + clear(); + } + reference at(size_type index) { assert(index < size_); return (*this)[index]; @@ -82,33 +90,44 @@ class CircularArray { void pop_back() { assert(size_ > 0); + SetElement(back()); --size_; } void pop_front() { assert(size_ > 0); - front_ = (front_ + 1) & mask_; + SetElement(front()); + front_ = (front_ + 1) & kMask; --size_; } void push_back(const value_type& value) { assert(size_ < kCapacity); - contents_[position(size_++)] = value; + SetElement(at(size_++), value); } size_type size() const { return size_; } void clear() { - size_ = 0; + while (!empty()) { + pop_back(); + } } private: - std::array<T, kCapacity> contents_; - size_type size_; - size_type front_; - size_type mask_; + static const size_type kMask = kCapacity - 1; - size_t position(size_t index) const { return (front_ + index) & mask_; } + size_t position(size_t index) const { return (front_ + index) & kMask; } + + template <typename... Args> + void SetElement(reference element, Args&&... args) { + element.~T(); + new (&element) T(std::forward<Args>(args)...); + } + + std::array<T, kCapacity> contents_; + size_type size_ = 0; + size_type front_ = 0; }; } |