68 alignas(std::max_align_t)
73 const std::type_info* typeInfo;
77 static constexpr size_t kHeaderSize =
sizeof(Header);
102 size_t size()
const noexcept {
return size_; }
103 size_t capacity()
const noexcept {
return capacity_; }
104 bool empty()
const noexcept {
return size_ == 0; }
111 const std::type_info& elementType()
const noexcept;
114 bool hasType() const noexcept {
return data_ !=
nullptr; }
119 return data_ ? header()->elementSize : 0;
125 return data_ ? header()->ops :
nullptr;
132 void* data() noexcept {
return data_; }
133 const void* data() const noexcept {
return data_; }
140 void reserve(
size_t n);
143 void resize(
size_t n);
146 void resize(
size_t n,
const T& value);
150 void reset(
size_t n);
154 void reset(
size_t n,
const T& value);
157 void pushBack(
const T& value);
159 template<
typename T,
typename... Args>
160 void emplaceBack(Args&&... args);
189 Span<const T> asSpan()
const;
196 const T& at(
size_t i)
const;
206 const T* begin()
const;
212 const T* end()
const;
218 void swap(VariantVector& other)
noexcept;
225 static VariantVector fromVector(
const std::vector<T>& vec);
230 void destroy() noexcept;
231 void copyFrom(const VariantVector& other);
232 void moveFrom(VariantVector& other) noexcept;
234 inline Header* header() noexcept;
235 inline const Header* header() const noexcept;
251 void (*destroy)(
void* data,
size_t count);
252 void (*copyConstruct)(
void* dst,
const void* src,
size_t count);
253 void (*moveConstruct)(
void* dst,
void* src,
size_t count);
261 [](
void* data,
size_t count) {
262 T* p =
static_cast<T*
>(data);
263 for (
size_t i = 0; i < count; ++i)
267 [](
void* dst,
const void* src,
size_t count) {
268 const T*
s =
static_cast<const T*
>(src);
269 T* d =
static_cast<T*
>(dst);
270 for (
size_t i = 0; i < count; ++i)
271 ::new (
static_cast<void*
>(&d[i]))
T(
s[i]);
274 [](
void* dst,
void* src,
size_t count) {
275 T*
s =
static_cast<T*
>(src);
276 T* d =
static_cast<T*
>(dst);
277 for (
size_t i = 0; i < count; ++i)
278 ::new (
static_cast<void*
>(&d[i]))
T(std::move(
s[i]));
290inline VariantVector::Header* VariantVector::header() noexcept
292 assert(data_ !=
nullptr);
293 return reinterpret_cast<Header*
>(
static_cast<char*
>(data_) - kHeaderSize);
296inline const VariantVector::Header* VariantVector::header() const noexcept
298 assert(data_ !=
nullptr);
299 return reinterpret_cast<const Header*
>(
static_cast<const char*
>(data_) - kHeaderSize);
310inline void VariantVector::ensureType()
312 if (data_ !=
nullptr)
315 assert(*header()->typeInfo ==
typeid(T) &&
"VariantVector: type mismatch");
320 const TypeOps& typeOps = TypeOps::forType<T>();
321 void* block = ::operator
new(kHeaderSize);
322 ::new (block) Header{&typeOps, &
typeid(
T),
sizeof(T)};
323 data_ =
static_cast<char*
>(block) + kHeaderSize;
330inline void VariantVector::reserve(
size_t n)
337 const Header* oldHeader = header();
338 size_t elemSize = oldHeader->elementSize;
341 if (n > (SIZE_MAX - kHeaderSize) / elemSize)
342 throw std::length_error(
"VariantVector::reserve: requested size exceeds max_size");
344 size_t offset = kHeaderSize;
345 size_t newBlockSize = offset + n * elemSize;
346 char* newBlock =
static_cast<char*
>(::operator
new(newBlockSize));
349 ::new (newBlock) Header(*oldHeader);
352 char* newDataPtr = newBlock + offset;
357 oldHeader->ops->moveConstruct(newDataPtr, data_, size_);
361 ::operator
delete(
static_cast<void*
>(newBlock));
367 char* oldBlock =
static_cast<char*
>(data_) - offset;
369 oldHeader->ops->destroy(data_, size_);
370 ::operator
delete(
static_cast<void*
>(oldBlock));
380inline void VariantVector::resize(
size_t n)
388 T* p =
static_cast<T*
>(data_);
391 ::new (
static_cast<void*
>(&p[size_]))
T();
398 T* p =
static_cast<T*
>(data_);
399 for (
size_t i = n; i < size_; ++i)
408inline void VariantVector::resize(
size_t n,
const T& value)
416 T* p =
static_cast<T*
>(data_);
419 ::new (
static_cast<void*
>(&p[size_]))
T(value);
426 T* p =
static_cast<T*
>(data_);
427 for (
size_t i = n; i < size_; ++i)
436inline void VariantVector::reset(
size_t n)
442 T* p =
static_cast<T*
>(data_);
445 ::new (
static_cast<void*
>(&p[size_]))
T();
451inline void VariantVector::reset(
size_t n,
const T& value)
457 T* p =
static_cast<T*
>(data_);
460 ::new (
static_cast<void*
>(&p[size_]))
T(value);
468inline void VariantVector::pushBack(
const T& value)
472 if (size_ >= capacity_)
474 size_t newCap = (capacity_ == 0) ? 1 :
475 (capacity_ > SIZE_MAX / 2) ? SIZE_MAX : capacity_ * 2;
479 T* p =
static_cast<T*
>(data_);
480 ::new (
static_cast<void*
>(&p[size_])) T(value);
486template<
typename T,
typename... Args>
487inline void VariantVector::emplaceBack(Args&&... args)
491 if (size_ >= capacity_)
493 size_t newCap = (capacity_ == 0) ? 1 :
494 (capacity_ > SIZE_MAX / 2) ? SIZE_MAX : capacity_ * 2;
498 T* p =
static_cast<T*
>(data_);
499 ::new (
static_cast<void*
>(&p[size_]))
T(std::forward<Args>(args)...);
506inline T& VariantVector::at(
size_t i)
508 if (data_ ==
nullptr)
509 throw std::logic_error(
"VariantVector::at: vector has no type set");
511 if (*header()->typeInfo !=
typeid(
T))
512 throw std::logic_error(
"VariantVector::at: type mismatch");
515 throw std::out_of_range(
"VariantVector::at: index out of range");
517 return static_cast<T*
>(data_)[i];
521inline const T& VariantVector::at(
size_t i)
const
523 if (data_ ==
nullptr)
524 throw std::logic_error(
"VariantVector::at: vector has no type set");
526 if (*header()->typeInfo !=
typeid(T))
527 throw std::logic_error(
"VariantVector::at: type mismatch");
530 throw std::out_of_range(
"VariantVector::at: index out of range");
532 return static_cast<const T*
>(data_)[i];
538inline T* VariantVector::as()
540 if (data_ ==
nullptr)
return nullptr;
541 if (*header()->typeInfo !=
typeid(
T))
return nullptr;
542 return static_cast<T*
>(data_);
546inline const T* VariantVector::as()
const
548 if (data_ ==
nullptr)
return nullptr;
549 if (*header()->typeInfo !=
typeid(T))
return nullptr;
550 return static_cast<const T*
>(data_);
558 if (data_ ==
nullptr)
return Span<T>();
559 if (*header()->typeInfo !=
typeid(
T))
return Span<T>();
560 return Span<T>(
static_cast<T*
>(data_), size_);
567 if (*header()->typeInfo !=
typeid(T))
return Span<const T>();
574inline T* VariantVector::begin()
576 if (data_ ==
nullptr)
return nullptr;
577 if (*header()->typeInfo !=
typeid(T))
return nullptr;
578 return static_cast<T*
>(data_);
582inline const T* VariantVector::begin()
const
584 if (data_ ==
nullptr)
return nullptr;
585 if (*header()->typeInfo !=
typeid(T))
return nullptr;
586 return static_cast<const T*
>(data_);
590inline T* VariantVector::end()
592 if (data_ ==
nullptr)
return nullptr;
593 if (*header()->typeInfo !=
typeid(T))
return nullptr;
594 return static_cast<T*
>(data_) + size_;
598inline const T* VariantVector::end()
const
600 if (data_ ==
nullptr)
return nullptr;
601 if (*header()->typeInfo !=
typeid(T))
return nullptr;
602 return static_cast<const T*
>(data_) + size_;
608inline VariantVector VariantVector::fromVector(
const std::vector<T>& vec)
612 v.reserve<
T>(vec.size());
615 T* dst =
static_cast<T*
>(v.data_);
616 for (
size_t i = 0; i < vec.size(); ++i)
618 ::new (
static_cast<void*
>(&dst[i]))
T(vec[i]);
非拥有的连续对象序列视图
定义 Span.hpp:71
变类型向量容器
定义 VariantVector.hpp:59
const TypeOps * ops() const noexcept
获取 TypeOps 指针(未设置类型时返回 nullptr)
定义 VariantVector.hpp:123
bool hasType() const noexcept
是否已设置类型(即 data_ != nullptr)
定义 VariantVector.hpp:114
size_t elementSize() const noexcept
元素大小(未设置类型时返回 0)
定义 VariantVector.hpp:117
static const TypeOps & forType()
获取类型 T 对应的 TypeOps 单例
定义 VariantVector.hpp:257