[libc-commits] [libc] [libc][CPP] Add vector container and unit tests (PR #222972)
Jeff Bailey via libc-commits
libc-commits at lists.llvm.org
Fri Sep 11 11:50:02 PDT 2026
================
@@ -0,0 +1,321 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation of vector container.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_VECTOR_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_VECTOR_H
+
+#include "hdr/func/free.h"
+#include "hdr/func/realloc.h"
+#include "hdr/types/size_t.h"
+#include "src/__support/CPP/new.h"
+#include "src/__support/CPP/type_traits.h"
+#include "src/__support/CPP/utility.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_assert.h"
+#include "src/__support/macros/config.h"
+
+#include <stddef.h> // For max_align_t, ptrdiff_t
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+template <typename T> class vector {
+ static_assert(alignof(T) <= alignof(max_align_t),
+ "Overaligned types are not supported by cpp::vector");
+
+public:
+ using value_type = T;
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
+ using reference = T &;
+ using const_reference = const T &;
+ using pointer = T *;
+ using const_pointer = const T *;
+ using iterator = T *;
+ using const_iterator = const T *;
+
+ [[nodiscard]] LIBC_INLINE constexpr size_type max_size() const noexcept {
+ return static_cast<size_type>(-1) / sizeof(T);
+ }
+
+private:
+ T *data_ = nullptr;
+ size_t size_ = 0;
+ size_t capacity_ = 0;
+
+ static constexpr size_t DEFAULT_INITIAL_CAPACITY = 16;
+
+ LIBC_INLINE void destroy_elements(size_t from, size_t to) {
+ if constexpr (!is_trivially_destructible_v<T>) {
+ while (to > from) {
+ --to;
+ data_[to].~T();
+ }
+ }
+ }
+
+ LIBC_INLINE void deallocate() {
+ if (data_) {
+ destroy_elements(0, size_);
+ ::free(data_);
+ data_ = nullptr;
+ size_ = 0;
+ capacity_ = 0;
+ }
+ }
+
+public:
+ LIBC_INLINE constexpr vector() = default;
+
+ LIBC_INLINE ~vector() { deallocate(); }
+
+ // Move constructor
+ LIBC_INLINE vector(vector &&other) noexcept
+ : data_(other.data_), size_(other.size_), capacity_(other.capacity_) {
+ other.data_ = nullptr;
+ other.size_ = 0;
+ other.capacity_ = 0;
+ }
+
+ // Move assignment
+ LIBC_INLINE vector &operator=(vector &&other) noexcept {
+ if (this != &other) {
+ deallocate();
+ data_ = other.data_;
+ size_ = other.size_;
+ capacity_ = other.capacity_;
+ other.data_ = nullptr;
+ other.size_ = 0;
+ other.capacity_ = 0;
+ }
+ return *this;
+ }
+
+ // Copy operations are deleted to prevent accidental implicit allocations.
+ vector(const vector &) = delete;
+ vector &operator=(const vector &) = delete;
+
+ // Element access
+ LIBC_INLINE reference operator[](size_t i) {
+ LIBC_ASSERT(i < size_);
+ return data_[i];
+ }
+
+ LIBC_INLINE const_reference operator[](size_t i) const {
+ LIBC_ASSERT(i < size_);
+ return data_[i];
+ }
+
+ LIBC_INLINE pointer data() { return data_; }
+ LIBC_INLINE const_pointer data() const { return data_; }
+
+ LIBC_INLINE reference front() {
+ LIBC_ASSERT(size_ > 0);
+ return data_[0];
+ }
+
+ LIBC_INLINE const_reference front() const {
+ LIBC_ASSERT(size_ > 0);
+ return data_[0];
+ }
+
+ LIBC_INLINE reference back() {
+ LIBC_ASSERT(size_ > 0);
+ return data_[size_ - 1];
+ }
+
+ LIBC_INLINE const_reference back() const {
+ LIBC_ASSERT(size_ > 0);
+ return data_[size_ - 1];
+ }
+
+ // Iterators
+ LIBC_INLINE iterator begin() { return data_; }
+ LIBC_INLINE const_iterator begin() const { return data_; }
+ LIBC_INLINE const_iterator cbegin() const { return data_; }
+ LIBC_INLINE iterator end() { return data_ + size_; }
+ LIBC_INLINE const_iterator end() const { return data_ + size_; }
+ LIBC_INLINE const_iterator cend() const { return data_ + size_; }
+
+ // Capacity
+ [[nodiscard]] LIBC_INLINE bool empty() const { return size_ == 0; }
+ LIBC_INLINE size_t size() const { return size_; }
+ LIBC_INLINE size_t capacity() const { return capacity_; }
----------------
kaladron wrote:
It's all that's required per the C++ spec AFAICT. However, libc++ does annotate the others, so I'll do so too.
https://github.com/llvm/llvm-project/pull/222972
More information about the libc-commits
mailing list