summaryrefslogtreecommitdiff
path: root/src/circular-array.h
diff options
context:
space:
mode:
authorBen Smith <binjimin@gmail.com>2017-09-13 18:45:29 -0700
committerGitHub <noreply@github.com>2017-09-13 18:45:29 -0700
commit7a0bf623e2b69621fa45f2d194c9dd6233086203 (patch)
treeec6f782dba8b8b1d8d3dd5c201097056a5f33c3c /src/circular-array.h
parente592d8d95a2d1a21d04e8311ef1aaee07be26e62 (diff)
downloadwabt-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.h41
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;
};
}