You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
CppCoreGuidelines/docs/dyn_array.md

4.0 KiB

gsl::dyn_array<T, Allocator>

gsl::dyn_array is a dynamic array that is intended to be a replacement for slinging around raw pointers and sizes. Notably, it owns all of its elements. It should replace the following idioms:

  • Replace new T[n] with gsl::dyn_array<T>(n).
  • Replace both foo(T*, size_t) and foo(unique_ptr<T[]>&, size_t) with foo(gsl::dyn_array<T>&).

It can be thought of like a...

  • std::array except the size is specified at runtime.
  • std::vector except it can neither shrink nor grow.

By design, gsl::dyn_array is not a Container as defined by the C++ Named Requirements because we want to avoid the invalidation of iterators or references to gsl::dyn_array objects. Furthermore, by design, there is no support for operations (other than destruction) that can invalidate iterators or pointers into the sequence owned by a gsl::dyna_array object. An gsl::dyn_array object cannot be moved, nor can it be copied.

Construction

gsl::dyn_arrays can be constructed in the following ways:

  • Default construct a dyn_array with no elements:
constexpr dyn_array();
  • Move construct a dyn_array from other: not possible
dyn_array(dyn_array&& other) = delete;
  • Construct a dyn_array with n default constructed elements:
constexpr explicit dyn_array(size_t n, const Allocator & alloc = Allocator());
  • Construct a dyn_array with n elements, each copy constructed from arg:
constexpr dyn_array(size_t n, const T& arg, const Allocator & alloc = Allocator());
  • Construct a dyn_array with elements from the range [first, last):
template <typename InputIt>
#ifdef __cpp_lib_concepts
    requires(std::input_iterator<InputIt>)
#endif /* __cpp_lib_concepts */
constexpr dyn_array(InputIt first, InputIt last, const Allocator & alloc = Allocator());
  • Construct a dyn_array from a range:
#ifdef __cpp_lib_containers_range
template <typename R>
    requires(std::ranges::range<R>)
constexpr dyn_array(std::from_range_t, R&& r, const Allocator & alloc = Allocator());
#endif /* __cpp_lib_containers_range */
  • Construct a dyn_array with elements from the initializer list:
constexpr dyn_array(std::initializer_list<T>, const Allocator & alloc = Allocator());

Operations

In addition to the operations required by the named requirements, gsl::dyn_array will support the following operations:

  • Access the specified element with bounds checking:
constexpr T& operator[](size_t);
constexpr const T& operator[](size_t) const;
  • Access the underlying array:
constexpr T* data() noexcept;
constexpr const T* data() const noexcept;
  • Return the number of elements in the dyn_array:
constexpr size_t size() const noexcept;

FAQ

Why no push_back (and friends)?

gsl::dyn_array is intended to be a fixed-size array and all objects should be constructed at creation. It supports no iterator/pointer-invalidating operation.

Why does gsl::dyn_array not conform to the Container Named Requirements?

gsl::dyn_array is intended to be a safer replacement for raw pointers and sizes. We don't want users to accidentally use it in a way that would be unsafe. For example, gsl::dyn_array does not have copy or move operations. This is because it would be possible to invalidate existing iterators and references.

Bounds Checking Semantics

If an out-of-bounds access (read or write) is attempted, gsl::dyn_array should follow the contract violation strategy outlined in GSL.assert: Assertions.

References