---
# System prepended metadata

title: 'base::HeapArray'
tags: [Chromium-General, elkurin-daily-note]

---

# base::HeapArray

[base::HeapArray](https://source.chromium.org/chromium/chromium/src/+/main:base/containers/heap_array.h)は配列のユニークポインタ型`std::unique_ptr<T[]>`の代替実装で、サイズをトラックしてくれる。

2024年から実装されている絶賛開発中のライブラリで、新しく追加されたので確認してみる。  

## 概要

`std::unique_ptr<T[]>`型の`data_`と、`size_t`型の`size_`の2つをデータとして持つオブジェクト。  
いずれの値も`data()`, `size()`のアクセッサーがある。

HeapArrayはconstや参照を要素として取ることはできないことに注意。

ownされた配列へのアクセスということでbase::span型と互換性が高い。  
例えばbase::spanからコピーして作れる[CopiedFrom](https://source.chromium.org/chromium/chromium/src/+/main:base/containers/heap_array.h;l=62;drc=f4a00cc248dd2dc8ec8759fb51620d47b5114090)というstatic constructorや、中身をspanとして取り出す[as_span](https://source.chromium.org/chromium/chromium/src/+/main:base/containers/heap_array.h;l=121;drc=f4a00cc248dd2dc8ec8759fb51620d47b5114090), [subspan](https://source.chromium.org/chromium/chromium/src/+/main:base/containers/heap_array.h;l=138;drc=f4a00cc248dd2dc8ec8759fb51620d47b5114090)がある。  
ただしlifetime boundがある。

### Lifetime Bound
`data`へのアクセッサーや、spanとして扱うメソッドには[ABSL_ATTRIBUTE_LIFETIME_BOUND](https://source.chromium.org/chromium/chromium/src/+/main:third_party/abseil-cpp/absl/base/attributes.h;l=812;drc=f4a00cc248dd2dc8ec8759fb51620d47b5114090)のアトリビュートがつけられている。これは何？

[clang](https://clang.llvm.org/docs/AttributeReference.html#lifetimebound)のドキュメントによると、返り値やコンストラクトしたオブジェクトがその元の関数・コンストラクタのパラメータを参照するかもしれないことを意味している。  
もしこの一時オブジェクトのライフタイムが参照元より短い場合はwarningが出るようになるらしい。

## コンストラクタ
初期化は[WithSize](https://source.chromium.org/chromium/chromium/src/+/main:base/containers/heap_array.h;l=40;drc=d09479a2882077ad7d39475ff98f8e146ea9ef60)か[Uninit](https://source.chromium.org/chromium/chromium/src/+/main:base/containers/heap_array.h;l=52;drc=f4a00cc248dd2dc8ec8759fb51620d47b5114090)のstatic constructorを使ってサイズとともに行う。  
空の場合は[default ctor](https://source.chromium.org/chromium/chromium/src/+/main:base/containers/heap_array.h;l=69;drc=f4a00cc248dd2dc8ec8759fb51620d47b5114090)も使える。どれを使っても空の場合メモリはallocateされない。

```cpp=
// 空
HeapArray()
    requires(std::constructible_from<T>)
  = default;

// sizeとともに作る。
static HeapArray WithSize(size_t size)
  requires(std::constructible_from<T>)
{
  if (!size) {
    return HeapArray();
  }
  return HeapArray(std::unique_ptr<T[]>(new T[size]()), size);
}

// WithSizeと同様sizeから作るが、こちらはuninitialized memoryをallocateする。
static HeapArray Uninit(size_t size)
  requires(std::is_trivially_constructible_v<T> &&
           std::is_trivially_destructible_v<T>)
{
  if (!size) {
    return HeapArray();
  }
  return HeapArray(std::unique_ptr<T[]>(new T[size]), size);
}
```

中身がunique_ptrなのでcopy constructorがdeleteされている。  
moveはconstructorもassign operatorも定義されている。  
```cpp=
HeapArray(HeapArray&& that)
    : data_(std::move(that.data_)), size_(std::exchange(that.size_, 0u)) {}
```
move元は`size_`をきちんと0にきょき化。


## 要素へのアクセス
i番目の要素にアクセスしたい場合は普通の配列と同じように`v[]`オペレータがサポートされている。
```cpp=
T& operator[](size_t idx) ABSL_ATTRIBUTE_LIFETIME_BOUND {
  return as_span()[idx];
}
```

またiteratorは`iterator = base::span<T>::iterator`としてbegin,endがされている。