Bitcoin Core 28.99.0
P2P Digital Currency
prevector.h
Go to the documentation of this file.
1// Copyright (c) 2015-2022 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#ifndef BITCOIN_PREVECTOR_H
6#define BITCOIN_PREVECTOR_H
7
8#include <algorithm>
9#include <cassert>
10#include <cstddef>
11#include <cstdint>
12#include <cstdlib>
13#include <cstring>
14#include <iterator>
15#include <type_traits>
16#include <utility>
17
36template<unsigned int N, typename T, typename Size = uint32_t, typename Diff = int32_t>
37class prevector {
38 static_assert(std::is_trivially_copyable_v<T>);
39
40public:
41 typedef Size size_type;
42 typedef Diff difference_type;
43 typedef T value_type;
47 typedef const value_type* const_pointer;
48
49 class iterator {
50 T* ptr{};
51 public:
52 typedef Diff difference_type;
53 typedef T* pointer;
54 typedef T& reference;
55 using element_type = T;
56 using iterator_category = std::contiguous_iterator_tag;
57 iterator() = default;
58 iterator(T* ptr_) : ptr(ptr_) {}
59 T& operator*() const { return *ptr; }
60 T* operator->() const { return ptr; }
61 T& operator[](size_type pos) const { return ptr[pos]; }
62 iterator& operator++() { ptr++; return *this; }
63 iterator& operator--() { ptr--; return *this; }
64 iterator operator++(int) { iterator copy(*this); ++(*this); return copy; }
65 iterator operator--(int) { iterator copy(*this); --(*this); return copy; }
66 difference_type friend operator-(iterator a, iterator b) { return (&(*a) - &(*b)); }
67 iterator operator+(size_type n) const { return iterator(ptr + n); }
68 iterator friend operator+(size_type n, iterator x) { return x + n; }
69 iterator& operator+=(size_type n) { ptr += n; return *this; }
70 iterator operator-(size_type n) const { return iterator(ptr - n); }
71 iterator& operator-=(size_type n) { ptr -= n; return *this; }
72 bool operator==(iterator x) const { return ptr == x.ptr; }
73 bool operator!=(iterator x) const { return ptr != x.ptr; }
74 bool operator>=(iterator x) const { return ptr >= x.ptr; }
75 bool operator<=(iterator x) const { return ptr <= x.ptr; }
76 bool operator>(iterator x) const { return ptr > x.ptr; }
77 bool operator<(iterator x) const { return ptr < x.ptr; }
78 };
79
81 T* ptr{};
82 public:
83 typedef Diff difference_type;
84 typedef T value_type;
85 typedef T* pointer;
86 typedef T& reference;
87 typedef std::bidirectional_iterator_tag iterator_category;
88 reverse_iterator() = default;
89 reverse_iterator(T* ptr_) : ptr(ptr_) {}
90 T& operator*() const { return *ptr; }
91 T* operator->() const { return ptr; }
92 reverse_iterator& operator--() { ptr++; return *this; }
93 reverse_iterator& operator++() { ptr--; return *this; }
94 reverse_iterator operator++(int) { reverse_iterator copy(*this); ++(*this); return copy; }
95 reverse_iterator operator--(int) { reverse_iterator copy(*this); --(*this); return copy; }
96 bool operator==(reverse_iterator x) const { return ptr == x.ptr; }
97 bool operator!=(reverse_iterator x) const { return ptr != x.ptr; }
98 };
99
101 const T* ptr{};
102 public:
103 typedef Diff difference_type;
104 typedef const T* pointer;
105 typedef const T& reference;
106 using element_type = const T;
107 using iterator_category = std::contiguous_iterator_tag;
108 const_iterator() = default;
109 const_iterator(const T* ptr_) : ptr(ptr_) {}
111 const T& operator*() const { return *ptr; }
112 const T* operator->() const { return ptr; }
113 const T& operator[](size_type pos) const { return ptr[pos]; }
114 const_iterator& operator++() { ptr++; return *this; }
115 const_iterator& operator--() { ptr--; return *this; }
116 const_iterator operator++(int) { const_iterator copy(*this); ++(*this); return copy; }
117 const_iterator operator--(int) { const_iterator copy(*this); --(*this); return copy; }
118 difference_type friend operator-(const_iterator a, const_iterator b) { return (&(*a) - &(*b)); }
120 const_iterator friend operator+(size_type n, const_iterator x) { return x + n; }
121 const_iterator& operator+=(size_type n) { ptr += n; return *this; }
123 const_iterator& operator-=(size_type n) { ptr -= n; return *this; }
124 bool operator==(const_iterator x) const { return ptr == x.ptr; }
125 bool operator!=(const_iterator x) const { return ptr != x.ptr; }
126 bool operator>=(const_iterator x) const { return ptr >= x.ptr; }
127 bool operator<=(const_iterator x) const { return ptr <= x.ptr; }
128 bool operator>(const_iterator x) const { return ptr > x.ptr; }
129 bool operator<(const_iterator x) const { return ptr < x.ptr; }
130 };
131
133 const T* ptr{};
134 public:
135 typedef Diff difference_type;
136 typedef const T value_type;
137 typedef const T* pointer;
138 typedef const T& reference;
139 typedef std::bidirectional_iterator_tag iterator_category;
141 const_reverse_iterator(const T* ptr_) : ptr(ptr_) {}
143 const T& operator*() const { return *ptr; }
144 const T* operator->() const { return ptr; }
145 const_reverse_iterator& operator--() { ptr++; return *this; }
146 const_reverse_iterator& operator++() { ptr--; return *this; }
147 const_reverse_iterator operator++(int) { const_reverse_iterator copy(*this); ++(*this); return copy; }
148 const_reverse_iterator operator--(int) { const_reverse_iterator copy(*this); --(*this); return copy; }
149 bool operator==(const_reverse_iterator x) const { return ptr == x.ptr; }
150 bool operator!=(const_reverse_iterator x) const { return ptr != x.ptr; }
151 };
152
153private:
154#pragma pack(push, 1)
156 char direct[sizeof(T) * N];
157 struct {
158 char* indirect;
161 };
162#pragma pack(pop)
163 alignas(char*) direct_or_indirect _union = {};
165
166 static_assert(alignof(char*) % alignof(size_type) == 0 && sizeof(char*) % alignof(size_type) == 0, "size_type cannot have more restrictive alignment requirement than pointer");
167 static_assert(alignof(char*) % alignof(T) == 0, "value_type T cannot have more restrictive alignment requirement than pointer");
168
169 T* direct_ptr(difference_type pos) { return reinterpret_cast<T*>(_union.direct) + pos; }
170 const T* direct_ptr(difference_type pos) const { return reinterpret_cast<const T*>(_union.direct) + pos; }
171 T* indirect_ptr(difference_type pos) { return reinterpret_cast<T*>(_union.indirect_contents.indirect) + pos; }
172 const T* indirect_ptr(difference_type pos) const { return reinterpret_cast<const T*>(_union.indirect_contents.indirect) + pos; }
173 bool is_direct() const { return _size <= N; }
174
175 void change_capacity(size_type new_capacity) {
176 if (new_capacity <= N) {
177 if (!is_direct()) {
178 T* indirect = indirect_ptr(0);
179 T* src = indirect;
180 T* dst = direct_ptr(0);
181 memcpy(dst, src, size() * sizeof(T));
182 free(indirect);
183 _size -= N + 1;
184 }
185 } else {
186 if (!is_direct()) {
187 /* FIXME: Because malloc/realloc here won't call new_handler if allocation fails, assert
188 success. These should instead use an allocator or new/delete so that handlers
189 are called as necessary, but performance would be slightly degraded by doing so. */
190 _union.indirect_contents.indirect = static_cast<char*>(realloc(_union.indirect_contents.indirect, ((size_t)sizeof(T)) * new_capacity));
192 _union.indirect_contents.capacity = new_capacity;
193 } else {
194 char* new_indirect = static_cast<char*>(malloc(((size_t)sizeof(T)) * new_capacity));
195 assert(new_indirect);
196 T* src = direct_ptr(0);
197 T* dst = reinterpret_cast<T*>(new_indirect);
198 memcpy(dst, src, size() * sizeof(T));
199 _union.indirect_contents.indirect = new_indirect;
200 _union.indirect_contents.capacity = new_capacity;
201 _size += N + 1;
202 }
203 }
204 }
205
206 T* item_ptr(difference_type pos) { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); }
207 const T* item_ptr(difference_type pos) const { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); }
208
209 void fill(T* dst, ptrdiff_t count, const T& value = T{}) {
210 std::fill_n(dst, count, value);
211 }
212
213 template <std::input_iterator InputIterator>
214 void fill(T* dst, InputIterator first, InputIterator last) {
215 while (first != last) {
216 new(static_cast<void*>(dst)) T(*first);
217 ++dst;
218 ++first;
219 }
220 }
221
222public:
223 void assign(size_type n, const T& val) {
224 clear();
225 if (capacity() < n) {
227 }
228 _size += n;
229 fill(item_ptr(0), n, val);
230 }
231
232 template <std::input_iterator InputIterator>
233 void assign(InputIterator first, InputIterator last) {
234 size_type n = last - first;
235 clear();
236 if (capacity() < n) {
238 }
239 _size += n;
240 fill(item_ptr(0), first, last);
241 }
242
243 prevector() = default;
244
245 explicit prevector(size_type n) {
246 resize(n);
247 }
248
249 explicit prevector(size_type n, const T& val) {
251 _size += n;
252 fill(item_ptr(0), n, val);
253 }
254
255 template <std::input_iterator InputIterator>
256 prevector(InputIterator first, InputIterator last) {
257 size_type n = last - first;
259 _size += n;
260 fill(item_ptr(0), first, last);
261 }
262
264 size_type n = other.size();
266 _size += n;
267 fill(item_ptr(0), other.begin(), other.end());
268 }
269
271 : _union(std::move(other._union)), _size(other._size)
272 {
273 other._size = 0;
274 }
275
277 if (&other == this) {
278 return *this;
279 }
280 assign(other.begin(), other.end());
281 return *this;
282 }
283
285 if (!is_direct()) {
287 }
288 _union = std::move(other._union);
289 _size = other._size;
290 other._size = 0;
291 return *this;
292 }
293
294 size_type size() const {
295 return is_direct() ? _size : _size - N - 1;
296 }
297
298 bool empty() const {
299 return size() == 0;
300 }
301
302 iterator begin() { return iterator(item_ptr(0)); }
306
311
312 size_t capacity() const {
313 if (is_direct()) {
314 return N;
315 } else {
317 }
318 }
319
321 return *item_ptr(pos);
322 }
323
324 const T& operator[](size_type pos) const {
325 return *item_ptr(pos);
326 }
327
328 void resize(size_type new_size) {
329 size_type cur_size = size();
330 if (cur_size == new_size) {
331 return;
332 }
333 if (cur_size > new_size) {
334 erase(item_ptr(new_size), end());
335 return;
336 }
337 if (new_size > capacity()) {
338 change_capacity(new_size);
339 }
340 ptrdiff_t increase = new_size - cur_size;
341 fill(item_ptr(cur_size), increase);
342 _size += increase;
343 }
344
345 void reserve(size_type new_capacity) {
346 if (new_capacity > capacity()) {
347 change_capacity(new_capacity);
348 }
349 }
350
353 }
354
355 void clear() {
356 resize(0);
357 }
358
359 iterator insert(iterator pos, const T& value) {
360 size_type p = pos - begin();
361 size_type new_size = size() + 1;
362 if (capacity() < new_size) {
363 change_capacity(new_size + (new_size >> 1));
364 }
365 T* ptr = item_ptr(p);
366 T* dst = ptr + 1;
367 memmove(dst, ptr, (size() - p) * sizeof(T));
368 _size++;
369 new(static_cast<void*>(ptr)) T(value);
370 return iterator(ptr);
371 }
372
373 void insert(iterator pos, size_type count, const T& value) {
374 size_type p = pos - begin();
375 size_type new_size = size() + count;
376 if (capacity() < new_size) {
377 change_capacity(new_size + (new_size >> 1));
378 }
379 T* ptr = item_ptr(p);
380 T* dst = ptr + count;
381 memmove(dst, ptr, (size() - p) * sizeof(T));
382 _size += count;
383 fill(item_ptr(p), count, value);
384 }
385
386 template <std::input_iterator InputIterator>
387 void insert(iterator pos, InputIterator first, InputIterator last) {
388 size_type p = pos - begin();
389 difference_type count = last - first;
390 size_type new_size = size() + count;
391 if (capacity() < new_size) {
392 change_capacity(new_size + (new_size >> 1));
393 }
394 T* ptr = item_ptr(p);
395 T* dst = ptr + count;
396 memmove(dst, ptr, (size() - p) * sizeof(T));
397 _size += count;
398 fill(ptr, first, last);
399 }
400
401 inline void resize_uninitialized(size_type new_size) {
402 // resize_uninitialized changes the size of the prevector but does not initialize it.
403 // If size < new_size, the added elements must be initialized explicitly.
404 if (capacity() < new_size) {
405 change_capacity(new_size);
406 _size += new_size - size();
407 return;
408 }
409 if (new_size < size()) {
410 erase(item_ptr(new_size), end());
411 } else {
412 _size += new_size - size();
413 }
414 }
415
417 return erase(pos, pos + 1);
418 }
419
421 // Erase is not allowed to the change the object's capacity. That means
422 // that when starting with an indirectly allocated prevector with
423 // size and capacity > N, the result may be a still indirectly allocated
424 // prevector with size <= N and capacity > N. A shrink_to_fit() call is
425 // necessary to switch to the (more efficient) directly allocated
426 // representation (with capacity N and size <= N).
427 iterator p = first;
428 char* endp = (char*)&(*end());
429 _size -= last - p;
430 memmove(&(*first), &(*last), endp - ((char*)(&(*last))));
431 return first;
432 }
433
434 template<typename... Args>
435 void emplace_back(Args&&... args) {
436 size_type new_size = size() + 1;
437 if (capacity() < new_size) {
438 change_capacity(new_size + (new_size >> 1));
439 }
440 new(item_ptr(size())) T(std::forward<Args>(args)...);
441 _size++;
442 }
443
444 void push_back(const T& value) {
445 emplace_back(value);
446 }
447
448 void pop_back() {
449 erase(end() - 1, end());
450 }
451
452 T& front() {
453 return *item_ptr(0);
454 }
455
456 const T& front() const {
457 return *item_ptr(0);
458 }
459
460 T& back() {
461 return *item_ptr(size() - 1);
462 }
463
464 const T& back() const {
465 return *item_ptr(size() - 1);
466 }
467
468 void swap(prevector<N, T, Size, Diff>& other) noexcept
469 {
470 std::swap(_union, other._union);
471 std::swap(_size, other._size);
472 }
473
475 if (!is_direct()) {
478 }
479 }
480
481 bool operator==(const prevector<N, T, Size, Diff>& other) const {
482 if (other.size() != size()) {
483 return false;
484 }
485 const_iterator b1 = begin();
486 const_iterator b2 = other.begin();
487 const_iterator e1 = end();
488 while (b1 != e1) {
489 if ((*b1) != (*b2)) {
490 return false;
491 }
492 ++b1;
493 ++b2;
494 }
495 return true;
496 }
497
498 bool operator!=(const prevector<N, T, Size, Diff>& other) const {
499 return !(*this == other);
500 }
501
502 bool operator<(const prevector<N, T, Size, Diff>& other) const {
503 if (size() < other.size()) {
504 return true;
505 }
506 if (size() > other.size()) {
507 return false;
508 }
509 const_iterator b1 = begin();
510 const_iterator b2 = other.begin();
511 const_iterator e1 = end();
512 while (b1 != e1) {
513 if ((*b1) < (*b2)) {
514 return true;
515 }
516 if ((*b2) < (*b1)) {
517 return false;
518 }
519 ++b1;
520 ++b2;
521 }
522 return false;
523 }
524
525 size_t allocated_memory() const {
526 if (is_direct()) {
527 return 0;
528 } else {
529 return ((size_t)(sizeof(T))) * _union.indirect_contents.capacity;
530 }
531 }
532
534 return item_ptr(0);
535 }
536
537 const value_type* data() const {
538 return item_ptr(0);
539 }
540};
541
542#endif // BITCOIN_PREVECTOR_H
ArgsManager & args
Definition: bitcoind.cpp:277
bool operator==(const_iterator x) const
Definition: prevector.h:124
const_iterator & operator++()
Definition: prevector.h:114
const_iterator & operator+=(size_type n)
Definition: prevector.h:121
const_iterator friend operator+(size_type n, const_iterator x)
Definition: prevector.h:120
bool operator<(const_iterator x) const
Definition: prevector.h:129
const_iterator & operator-=(size_type n)
Definition: prevector.h:123
const_iterator operator--(int)
Definition: prevector.h:117
bool operator<=(const_iterator x) const
Definition: prevector.h:127
const_iterator operator++(int)
Definition: prevector.h:116
const_iterator(const T *ptr_)
Definition: prevector.h:109
const T * operator->() const
Definition: prevector.h:112
difference_type friend operator-(const_iterator a, const_iterator b)
Definition: prevector.h:118
bool operator!=(const_iterator x) const
Definition: prevector.h:125
const_iterator operator-(size_type n) const
Definition: prevector.h:122
bool operator>=(const_iterator x) const
Definition: prevector.h:126
const_iterator & operator--()
Definition: prevector.h:115
const T & operator*() const
Definition: prevector.h:111
const_iterator operator+(size_type n) const
Definition: prevector.h:119
std::contiguous_iterator_tag iterator_category
Definition: prevector.h:107
const T & operator[](size_type pos) const
Definition: prevector.h:113
bool operator>(const_iterator x) const
Definition: prevector.h:128
const_iterator(iterator x)
Definition: prevector.h:110
const_reverse_iterator(const T *ptr_)
Definition: prevector.h:141
const_reverse_iterator & operator--()
Definition: prevector.h:145
const_reverse_iterator operator--(int)
Definition: prevector.h:148
const_reverse_iterator operator++(int)
Definition: prevector.h:147
std::bidirectional_iterator_tag iterator_category
Definition: prevector.h:139
const_reverse_iterator(reverse_iterator x)
Definition: prevector.h:142
const T * operator->() const
Definition: prevector.h:144
bool operator!=(const_reverse_iterator x) const
Definition: prevector.h:150
const_reverse_iterator & operator++()
Definition: prevector.h:146
bool operator==(const_reverse_iterator x) const
Definition: prevector.h:149
std::contiguous_iterator_tag iterator_category
Definition: prevector.h:56
bool operator<(iterator x) const
Definition: prevector.h:77
bool operator==(iterator x) const
Definition: prevector.h:72
difference_type friend operator-(iterator a, iterator b)
Definition: prevector.h:66
iterator operator-(size_type n) const
Definition: prevector.h:70
T & operator[](size_type pos) const
Definition: prevector.h:61
bool operator!=(iterator x) const
Definition: prevector.h:73
iterator & operator++()
Definition: prevector.h:62
iterator operator--(int)
Definition: prevector.h:65
bool operator<=(iterator x) const
Definition: prevector.h:75
bool operator>=(iterator x) const
Definition: prevector.h:74
T & operator*() const
Definition: prevector.h:59
iterator & operator+=(size_type n)
Definition: prevector.h:69
iterator operator+(size_type n) const
Definition: prevector.h:67
T * operator->() const
Definition: prevector.h:60
iterator & operator-=(size_type n)
Definition: prevector.h:71
iterator operator++(int)
Definition: prevector.h:64
bool operator>(iterator x) const
Definition: prevector.h:76
iterator & operator--()
Definition: prevector.h:63
iterator friend operator+(size_type n, iterator x)
Definition: prevector.h:68
iterator(T *ptr_)
Definition: prevector.h:58
std::bidirectional_iterator_tag iterator_category
Definition: prevector.h:87
reverse_iterator operator++(int)
Definition: prevector.h:94
reverse_iterator & operator--()
Definition: prevector.h:92
bool operator!=(reverse_iterator x) const
Definition: prevector.h:97
bool operator==(reverse_iterator x) const
Definition: prevector.h:96
reverse_iterator operator--(int)
Definition: prevector.h:95
reverse_iterator & operator++()
Definition: prevector.h:93
Implements a drop-in replacement for std::vector<T> which stores up to N elements directly (without h...
Definition: prevector.h:37
bool empty() const
Definition: prevector.h:298
prevector(size_type n)
Definition: prevector.h:245
void change_capacity(size_type new_capacity)
Definition: prevector.h:175
void fill(T *dst, ptrdiff_t count, const T &value=T{})
Definition: prevector.h:209
void pop_back()
Definition: prevector.h:448
iterator erase(iterator first, iterator last)
Definition: prevector.h:420
prevector(InputIterator first, InputIterator last)
Definition: prevector.h:256
void swap(prevector< N, T, Size, Diff > &other) noexcept
Definition: prevector.h:468
prevector & operator=(prevector< N, T, Size, Diff > &&other) noexcept
Definition: prevector.h:284
Diff difference_type
Definition: prevector.h:42
const value_type & const_reference
Definition: prevector.h:45
size_type _size
Definition: prevector.h:164
void shrink_to_fit()
Definition: prevector.h:351
void clear()
Definition: prevector.h:355
value_type & reference
Definition: prevector.h:44
~prevector()
Definition: prevector.h:474
size_type size() const
Definition: prevector.h:294
reverse_iterator rend()
Definition: prevector.h:309
T & front()
Definition: prevector.h:452
bool operator==(const prevector< N, T, Size, Diff > &other) const
Definition: prevector.h:481
iterator erase(iterator pos)
Definition: prevector.h:416
prevector(size_type n, const T &val)
Definition: prevector.h:249
void fill(T *dst, InputIterator first, InputIterator last)
Definition: prevector.h:214
Size size_type
Definition: prevector.h:41
const T * indirect_ptr(difference_type pos) const
Definition: prevector.h:172
size_t capacity() const
Definition: prevector.h:312
T * direct_ptr(difference_type pos)
Definition: prevector.h:169
const_iterator end() const
Definition: prevector.h:305
const T & front() const
Definition: prevector.h:456
direct_or_indirect _union
Definition: prevector.h:163
void assign(InputIterator first, InputIterator last)
Definition: prevector.h:233
void emplace_back(Args &&... args)
Definition: prevector.h:435
bool is_direct() const
Definition: prevector.h:173
T & back()
Definition: prevector.h:460
void insert(iterator pos, InputIterator first, InputIterator last)
Definition: prevector.h:387
const T * item_ptr(difference_type pos) const
Definition: prevector.h:207
bool operator<(const prevector< N, T, Size, Diff > &other) const
Definition: prevector.h:502
value_type * data()
Definition: prevector.h:533
iterator begin()
Definition: prevector.h:302
T value_type
Definition: prevector.h:43
iterator end()
Definition: prevector.h:304
prevector()=default
const value_type * data() const
Definition: prevector.h:537
bool operator!=(const prevector< N, T, Size, Diff > &other) const
Definition: prevector.h:498
const T & back() const
Definition: prevector.h:464
void reserve(size_type new_capacity)
Definition: prevector.h:345
prevector(const prevector< N, T, Size, Diff > &other)
Definition: prevector.h:263
const T & operator[](size_type pos) const
Definition: prevector.h:324
const T * direct_ptr(difference_type pos) const
Definition: prevector.h:170
void resize_uninitialized(size_type new_size)
Definition: prevector.h:401
const_reverse_iterator rbegin() const
Definition: prevector.h:308
T * item_ptr(difference_type pos)
Definition: prevector.h:206
T * indirect_ptr(difference_type pos)
Definition: prevector.h:171
prevector & operator=(const prevector< N, T, Size, Diff > &other)
Definition: prevector.h:276
void resize(size_type new_size)
Definition: prevector.h:328
size_t allocated_memory() const
Definition: prevector.h:525
iterator insert(iterator pos, const T &value)
Definition: prevector.h:359
value_type * pointer
Definition: prevector.h:46
reverse_iterator rbegin()
Definition: prevector.h:307
const_reverse_iterator rend() const
Definition: prevector.h:310
prevector(prevector< N, T, Size, Diff > &&other) noexcept
Definition: prevector.h:270
const value_type * const_pointer
Definition: prevector.h:47
void assign(size_type n, const T &val)
Definition: prevector.h:223
void insert(iterator pos, size_type count, const T &value)
Definition: prevector.h:373
void push_back(const T &value)
Definition: prevector.h:444
const_iterator begin() const
Definition: prevector.h:303
T & operator[](size_type pos)
Definition: prevector.h:320
static int count
struct prevector::direct_or_indirect::@2 indirect_contents
char direct[sizeof(T) *N]
Definition: prevector.h:156
assert(!tx.IsCoinBase())