aboutsummaryrefslogtreecommitdiff
path: root/src/prevector.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/prevector.h')
-rw-r--r--src/prevector.h23
1 files changed, 16 insertions, 7 deletions
diff --git a/src/prevector.h b/src/prevector.h
index f4ece738a8..6d690e7f96 100644
--- a/src/prevector.h
+++ b/src/prevector.h
@@ -15,7 +15,6 @@
#include <type_traits>
#include <utility>
-#pragma pack(push, 1)
/** Implements a drop-in replacement for std::vector<T> which stores up to N
* elements directly (without heap allocation). The types Size and Diff are
* used to store element counts, and can be any unsigned + signed type.
@@ -147,14 +146,20 @@ public:
};
private:
- size_type _size = 0;
+#pragma pack(push, 1)
union direct_or_indirect {
char direct[sizeof(T) * N];
struct {
- size_type capacity;
char* indirect;
+ size_type capacity;
};
- } _union = {};
+ };
+#pragma pack(pop)
+ alignas(char*) direct_or_indirect _union = {};
+ size_type _size = 0;
+
+ static_assert(alignof(char*) % alignof(size_type) == 0 && sizeof(char*) % alignof(size_type) == 0, "size_type cannot have more restrictive alignment requirement than pointer");
+ static_assert(alignof(char*) % alignof(T) == 0, "value_type T cannot have more restrictive alignment requirement than pointer");
T* direct_ptr(difference_type pos) { return reinterpret_cast<T*>(_union.direct) + pos; }
const T* direct_ptr(difference_type pos) const { return reinterpret_cast<const T*>(_union.direct) + pos; }
@@ -419,15 +424,20 @@ public:
return first;
}
- void push_back(const T& value) {
+ template<typename... Args>
+ void emplace_back(Args&&... args) {
size_type new_size = size() + 1;
if (capacity() < new_size) {
change_capacity(new_size + (new_size >> 1));
}
- new(item_ptr(size())) T(value);
+ new(item_ptr(size())) T(std::forward<Args>(args)...);
_size++;
}
+ void push_back(const T& value) {
+ emplace_back(value);
+ }
+
void pop_back() {
erase(end() - 1, end());
}
@@ -523,6 +533,5 @@ public:
return item_ptr(0);
}
};
-#pragma pack(pop)
#endif // BITCOIN_PREVECTOR_H