Skip to content

Commit 92b88ef

Browse files
committed
Update specification after review from C++ Core Guideliens
- Make sure iterators and references cannot be invalidated by any operations (besides destruction). - Update specification to annotate that some functions require certain language features (ranges and concepts). - Remove dependence on "Container" named requirements because they require iterator-invalidating behavior. - Explicitly add default and move constructors. - Fix some typos
1 parent 6fbe6bf commit 92b88ef

File tree

1 file changed

+36
-23
lines changed

1 file changed

+36
-23
lines changed

docs/dyn_array.md

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,22 @@ It can be thought of like a...
1515
* `std::array` except the size is specified at runtime.
1616
* `std::vector` except it can neither shrink nor grow.
1717

18-
### Container Named Requirements
19-
In order to allow element access using iterators and to align with various container
20-
idioms for `std::` algorithms, `gsl::dyn_array` should satisfy the following named
21-
requirements:
22-
23-
* Container ([link](https://en.cppreference.com/w/cpp/named_req/Container))
24-
* ReversibleContainer ([link](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer))
25-
* ContiguousContainer ([link](https://en.cppreference.com/w/cpp/named_req/ContiguousContainer))
26-
* SequenceContainer ([link](https://en.cppreference.com/w/cpp/named_req/SequenceContainer))
27-
* AllocatorAwareContainer ([link](https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer))
18+
By design, `gsl::dyn_array` is not a `Container` as defined by the C++ Named
19+
Requirements because we want to avoid the invalidation of iterators or references to
20+
`gsl::dyn_array` objects.
2821

2922
### Construction
30-
In addition to the constructors required by the named requirements (default, copy, and
31-
move), `gsl::dyn_array` will support the following constructors:
23+
`gsl::dyn_array`s can be constructed in the following ways:
24+
25+
* Default construct a `dyn_array` with no elements:
26+
```c++
27+
constexpr dyn_array();
28+
```
29+
30+
* Move construct a `dyn_array` from `other`:
31+
```c++
32+
constexpr dyn_array(dyn_array&& other) noexcept;
33+
```
3234
3335
* Construct a `dyn_array` with `n` default constructed elements:
3436
```c++
@@ -43,20 +45,24 @@ constexpr dyn_array(size_t n, const T& arg, const Allocator & alloc = Allocator(
4345
* Construct a `dyn_array` with elements from the range `[first, last)`:
4446
```c++
4547
template <typename InputIt>
46-
requires (std::input_iterator<InputIt>)
48+
#ifdef __cpp_lib_concepts
49+
requires(std::input_iterator<InputIt>)
50+
#endif /* __cpp_lib_concepts */
4751
constexpr dyn_array(InputIt first, InputIt last, const Allocator & alloc = Allocator());
4852
```
4953

50-
* Construct a `dyn_array` with elements from the initializer list:
54+
* Construct a `dyn_array` from a range:
5155
```c++
52-
constexpr dyn_array(std::initializer_list<T>, const Allocator & alloc = Allocator());
56+
#ifdef __cpp_lib_containers_range
57+
template <typename R>
58+
requires(std::ranges::range<R>)
59+
constexpr dyn_array(std::from_range_t, R&& r, const Allocator & alloc = Allocator());
60+
#endif /* __cpp_lib_containers_range */
5361
```
5462

55-
* Construct a `dyn_array` with elements from the range `R`:
63+
* Construct a `dyn_array` with elements from the initializer list:
5664
```c++
57-
template <typename R>
58-
requires (std::input_range<R>)
59-
constexpr dyn_array(R&&, const Allocator & alloc = Allocator());
65+
constexpr dyn_array(std::initializer_list<T>, const Allocator & alloc = Allocator());
6066
```
6167
6268
### Operations
@@ -66,7 +72,7 @@ support the following operations:
6672
* Access the specified element **_with bounds checking_**:
6773
```c++
6874
constexpr T& operator[](size_t);
69-
constexpr const T& operator[](size_t) const
75+
constexpr const T& operator[](size_t) const;
7076
```
7177

7278
* Access the underlying array:
@@ -80,10 +86,17 @@ constexpr const T* data() const noexcept;
8086
constexpr size_t size() const noexcept;
8187
```
8288

83-
#### Note: Why no push_back (and friends)?
89+
### FAQ
90+
91+
#### Why no push_back (and friends)?
8492
`gsl::dyn_array` is intended to be a fixed-size array and all objects should be
85-
constructed at creation. Moreover, the memory overhead of storing another member
86-
variable to track where to push the next item is not desired.
93+
constructed at creation.
94+
95+
#### Why does `gsl::dyn_array` not conform to the `Container` Named Requirements?
96+
`gsl::dyn_array` is intended to be a safer replacement for raw pointers and sizes. We
97+
don't want users to accidentally use it in a way that would be unsafe. For example,
98+
`gsl::dyn_array` does not have copy or move assignment operators. This is because it
99+
would be possible to invalidate existing iterators and references.
87100

88101
### Bounds Checking Semantics
89102
If an out-of-bounds access (read or write) is attempted, `gsl::dyn_array` should follow

0 commit comments

Comments
 (0)