66 struct alignas(std::max_align_t) Header
69 const std::type_info* typeInfo;
73 static constexpr size_t kHeaderSize =
sizeof(Header);
98 size_t size()
const noexcept {
return size_; }
99 size_t capacity()
const noexcept {
return capacity_; }
100 bool empty()
const noexcept {
return size_ == 0; }
107 const std::type_info& elementType()
const noexcept;
110 bool hasType() const noexcept {
return data_ !=
nullptr; }
115 return data_ ? header()->elementSize : 0;
121 return data_ ? header()->ops :
nullptr;
128 void* data() noexcept {
return data_; }
129 const void* data() const noexcept {
return data_; }
136 void reserve(
size_t n);
139 void resize(
size_t n);
142 void resize(
size_t n,
const T& value);
146 void reset(
size_t n);
150 void reset(
size_t n,
const T& value);
153 void pushBack(
const T& value);
155 template<
typename T,
typename... Args>
156 void emplaceBack(Args&&... args);
185 Span<const T> asSpan()
const;
192 const T& at(
size_t i)
const;
202 const T* begin()
const;
208 const T* end()
const;
214 void swap(VariantVector& other)
noexcept;
221 static VariantVector fromVector(
const std::vector<T>& vec);
226 void destroy() noexcept;
227 void copyFrom(const VariantVector& other);
228 void moveFrom(VariantVector& other) noexcept;
230 Header* header() noexcept;
231 const Header* header() const noexcept;
247 void (*destroy)(
void* data,
size_t count);
248 void (*copyConstruct)(
void* dst,
const void* src,
size_t count);
249 void (*moveConstruct)(
void* dst,
void* src,
size_t count);
257 [](
void* data,
size_t count) {
258 T* p =
static_cast<T*
>(data);
259 for (
size_t i = 0; i < count; ++i)
263 [](
void* dst,
const void* src,
size_t count) {
264 const T*
s =
static_cast<const T*
>(src);
265 T* d =
static_cast<T*
>(dst);
266 for (
size_t i = 0; i < count; ++i)
267 ::new (
static_cast<void*
>(&d[i])) T(
s[i]);
270 [](
void* dst,
void* src,
size_t count) {
271 T*
s =
static_cast<T*
>(src);
272 T* d =
static_cast<T*
>(dst);
273 for (
size_t i = 0; i < count; ++i)
274 ::new (
static_cast<void*
>(&d[i])) T(std::move(
s[i]));
286inline VariantVector::Header* VariantVector::header() noexcept
288 assert(data_ !=
nullptr);
289 return reinterpret_cast<Header*
>(
static_cast<char*
>(data_) - kHeaderSize);
292inline const VariantVector::Header* VariantVector::header() const noexcept
294 assert(data_ !=
nullptr);
295 return reinterpret_cast<const Header*
>(
static_cast<const char*
>(data_) - kHeaderSize);
306inline void VariantVector::ensureType()
308 if (data_ !=
nullptr)
311 assert(*header()->typeInfo ==
typeid(T) &&
"VariantVector: type mismatch");
316 const TypeOps& typeOps = TypeOps::forType<T>();
317 void* block = ::operator
new(kHeaderSize);
318 ::new (block) Header{&typeOps, &
typeid(T),
sizeof(T)};
319 data_ =
static_cast<char*
>(block) + kHeaderSize;
326inline void VariantVector::reserve(
size_t n)
333 const Header* oldHeader = header();
334 size_t elemSize = oldHeader->elementSize;
337 if (n > (SIZE_MAX - kHeaderSize) / elemSize)
338 throw std::length_error(
"VariantVector::reserve: requested size exceeds max_size");
340 size_t offset = kHeaderSize;
341 size_t newBlockSize = offset + n * elemSize;
342 char* newBlock =
static_cast<char*
>(::operator
new(newBlockSize));
345 ::new (newBlock) Header(*oldHeader);
348 char* newDataPtr = newBlock + offset;
353 oldHeader->ops->moveConstruct(newDataPtr, data_, size_);
357 ::operator
delete(
static_cast<void*
>(newBlock));
363 char* oldBlock =
static_cast<char*
>(data_) - offset;
365 oldHeader->ops->destroy(data_, size_);
366 ::operator
delete(
static_cast<void*
>(oldBlock));
376inline void VariantVector::resize(
size_t n)
384 T* p =
static_cast<T*
>(data_);
387 ::new (
static_cast<void*
>(&p[size_])) T();
394 T* p =
static_cast<T*
>(data_);
395 for (
size_t i = n; i < size_; ++i)
404inline void VariantVector::resize(
size_t n,
const T& value)
412 T* p =
static_cast<T*
>(data_);
415 ::new (
static_cast<void*
>(&p[size_])) T(value);
422 T* p =
static_cast<T*
>(data_);
423 for (
size_t i = n; i < size_; ++i)
432inline void VariantVector::reset(
size_t n)
438 T* p =
static_cast<T*
>(data_);
441 ::new (
static_cast<void*
>(&p[size_])) T();
447inline void VariantVector::reset(
size_t n,
const T& value)
453 T* p =
static_cast<T*
>(data_);
456 ::new (
static_cast<void*
>(&p[size_])) T(value);
464inline void VariantVector::pushBack(
const T& value)
468 if (size_ >= capacity_)
470 size_t newCap = (capacity_ == 0) ? 1 :
471 (capacity_ > SIZE_MAX / 2) ? SIZE_MAX : capacity_ * 2;
475 T* p =
static_cast<T*
>(data_);
476 ::new (
static_cast<void*
>(&p[size_])) T(value);
482template<
typename T,
typename... Args>
483inline void VariantVector::emplaceBack(Args&&... args)
487 if (size_ >= capacity_)
489 size_t newCap = (capacity_ == 0) ? 1 :
490 (capacity_ > SIZE_MAX / 2) ? SIZE_MAX : capacity_ * 2;
494 T* p =
static_cast<T*
>(data_);
495 ::new (
static_cast<void*
>(&p[size_])) T(std::forward<Args>(args)...);
502inline T& VariantVector::at(
size_t i)
504 if (data_ ==
nullptr)
505 throw std::logic_error(
"VariantVector::at: vector has no type set");
507 if (*header()->typeInfo !=
typeid(T))
508 throw std::logic_error(
"VariantVector::at: type mismatch");
511 throw std::out_of_range(
"VariantVector::at: index out of range");
513 return static_cast<T*
>(data_)[i];
517inline const T& VariantVector::at(
size_t i)
const
519 if (data_ ==
nullptr)
520 throw std::logic_error(
"VariantVector::at: vector has no type set");
522 if (*header()->typeInfo !=
typeid(T))
523 throw std::logic_error(
"VariantVector::at: type mismatch");
526 throw std::out_of_range(
"VariantVector::at: index out of range");
528 return static_cast<const T*
>(data_)[i];
534inline T* VariantVector::as()
536 if (data_ ==
nullptr)
return nullptr;
537 if (*header()->typeInfo !=
typeid(T))
return nullptr;
538 return static_cast<T*
>(data_);
542inline const T* VariantVector::as()
const
544 if (data_ ==
nullptr)
return nullptr;
545 if (*header()->typeInfo !=
typeid(T))
return nullptr;
546 return static_cast<const T*
>(data_);
554 if (data_ ==
nullptr)
return Span<T>();
555 if (*header()->typeInfo !=
typeid(T))
return Span<T>();
556 return Span<T>(
static_cast<T*
>(data_), size_);
563 if (*header()->typeInfo !=
typeid(T))
return Span<const T>();
570inline T* VariantVector::begin()
572 if (data_ ==
nullptr)
return nullptr;
573 if (*header()->typeInfo !=
typeid(T))
return nullptr;
574 return static_cast<T*
>(data_);
578inline const T* VariantVector::begin()
const
580 if (data_ ==
nullptr)
return nullptr;
581 if (*header()->typeInfo !=
typeid(T))
return nullptr;
582 return static_cast<const T*
>(data_);
586inline T* VariantVector::end()
588 if (data_ ==
nullptr)
return nullptr;
589 if (*header()->typeInfo !=
typeid(T))
return nullptr;
590 return static_cast<T*
>(data_) + size_;
594inline const T* VariantVector::end()
const
596 if (data_ ==
nullptr)
return nullptr;
597 if (*header()->typeInfo !=
typeid(T))
return nullptr;
598 return static_cast<const T*
>(data_) + size_;
604inline VariantVector VariantVector::fromVector(
const std::vector<T>& vec)
608 v.reserve<T>(vec.size());
611 T* dst =
static_cast<T*
>(v.data_);
612 for (
size_t i = 0; i < vec.size(); ++i)
614 ::new (
static_cast<void*
>(&dst[i])) T(vec[i]);
非拥有的连续对象序列视图
定义 Span.hpp:71
变类型向量容器
定义 VariantVector.hpp:59
const TypeOps * ops() const noexcept
获取 TypeOps 指针(未设置类型时返回 nullptr)
定义 VariantVector.hpp:119
bool hasType() const noexcept
是否已设置类型(即 data_ != nullptr)
定义 VariantVector.hpp:110
size_t elementSize() const noexcept
元素大小(未设置类型时返回 0)
定义 VariantVector.hpp:113
static const TypeOps & forType()
获取类型 T 对应的 TypeOps 单例
定义 VariantVector.hpp:253