Clingo
Loading...
Searching...
No Matches
immutable_array.hh
1#pragma once
2
3#include <clingo/util/immutable_value.hh>
4
5#include <algorithm>
6#include <span>
7#include <stdexcept>
8#include <vector>
9
10namespace CppClingo::Util {
11
14
18template <typename T> class immutable_array {
19 private:
20 using vector_type = std::vector<T>;
21
22 public:
24 using value_type = typename vector_type::value_type;
26 using const_reference = typename vector_type::const_reference;
28 using allocator_type = typename vector_type::allocator_type;
30 using size_type = typename vector_type::size_type;
32 using difference_type = typename vector_type::difference_type;
34 using const_pointer = typename vector_type::const_pointer;
36 using const_iterator = typename vector_type::const_iterator;
37
39 constexpr immutable_array() noexcept = default;
40
42 immutable_array(immutable_array const &other) noexcept = default;
43
45 immutable_array(immutable_array &&other) noexcept = default;
46
48 auto operator=(immutable_array const &other) noexcept -> immutable_array & = default;
49
51 auto operator=(immutable_array &&other) noexcept -> immutable_array & = default;
52
54 immutable_array(std::span<T> span) : immutable_array{span.begin(), span.end()} {}
55
57 immutable_array(std::span<T const> span) : immutable_array{span.begin(), span.end()} {}
58
62 immutable_array(std::vector<T> &&vec) {
63 if (!vec.empty()) {
64 vec.shrink_to_fit();
65 vec_ = Util::make_immutable<vector_type>(std::move(vec));
66 }
67 }
68
70 immutable_array(std::vector<T> const &vec) : immutable_array{vec.begin(), vec.end()} {}
71
73 immutable_array(std::initializer_list<T> init) : immutable_array(init.begin(), init.end()) {}
74
76 template <class It> immutable_array(It first, It last) {
77 if (first != last) {
78 vec_ = Util::make_immutable<vector_type>(first, last);
79 }
80 }
81
83 template <class It, class Pred> immutable_array(It first, It last, Pred conv) {
84 if (first != last) {
85 auto vec = vector_type{};
86 vec.reserve(std::distance(first, last));
87 for (auto it = first; it != last; ++it) {
88 vec.emplace_back(conv(*it));
89 }
90 vec_ = Util::make_immutable<vector_type>(std::move(vec));
91 }
92 }
93
97 [[nodiscard]] auto at(size_type pos) const -> const_reference {
98 if (pos >= size()) {
99 throw std::out_of_range("");
100 }
101 return operator[](pos);
102 }
103
105 auto operator[](size_type pos) const -> const_reference { return vec_->operator[](pos); }
106
108 [[nodiscard]] auto front() const -> const_reference { return vec_->front(); }
109
111 [[nodiscard]] auto back() const -> const_reference { return vec_->back(); }
112
114 [[nodiscard]] auto data() const -> T const * { return vector_().data(); }
115
117 [[nodiscard]] auto begin() const noexcept -> const_iterator { return vector_().begin(); }
118
120 [[nodiscard]] auto end() const noexcept -> const_iterator { return vector_().end(); }
121
123 [[nodiscard]] auto empty() const noexcept -> bool { return vector_().empty(); }
124
126 [[nodiscard]] auto size() const noexcept -> size_type { return vector_().size(); }
127
129 void swap(immutable_array &other) noexcept { swap(other.vec_, vec_); }
130
132 friend auto operator==(immutable_array const &lhs, immutable_array const &rhs) -> bool {
133 return lhs.vector_() == rhs.vector_();
134 }
135
137 friend auto operator<=>(immutable_array const &lhs, immutable_array const &rhs) {
138 return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
139 }
140
141 private:
142 [[nodiscard]] auto vector_() const -> std::vector<T> const & { return vec_ ? *vec_ : empty_(); }
143
144 static auto empty_() -> std::vector<T> const & {
145 static std::vector<T> res;
146 return res;
147 }
148 Util::immutable_value<vector_type> vec_;
149};
150
153
155template <class T> void swap(immutable_array<T> &lhs, immutable_array<T> &rhs) noexcept {
156 lhs.swap(rhs);
157}
158
162template <class T, class... Ts> auto make_immutable_array(Ts &&...args) -> immutable_array<T> {
163 std::vector<T> res;
164 res.reserve(sizeof...(Ts));
165 (res.emplace_back(std::forward<Ts>(args)), ...);
166 return immutable_array(std::move(res));
167}
168
170
171} // namespace CppClingo::Util
An immutable array with efficient copying.
Definition immutable_array.hh:18
typename vector_type::value_type value_type
The value type.
Definition immutable_array.hh:24
typename vector_type::size_type size_type
The unsigned size type.
Definition immutable_array.hh:30
typename vector_type::const_iterator const_iterator
Theconst iterator type.
Definition immutable_array.hh:36
typename vector_type::const_reference const_reference
The reference type.
Definition immutable_array.hh:26
immutable_array(std::span< T const > span)
Construct array copying values from the given span.
Definition immutable_array.hh:57
friend auto operator<=>(immutable_array const &lhs, immutable_array const &rhs)
Compare two vectors lexicographically.
Definition immutable_array.hh:137
immutable_array(std::initializer_list< T > init)
Construct array coping from the given initializer list.
Definition immutable_array.hh:73
immutable_array(std::vector< T > &&vec)
Construct array taking ownership of the given vector.
Definition immutable_array.hh:62
auto operator[](size_type pos) const -> const_reference
Get the element at the given index.
Definition immutable_array.hh:105
immutable_array(std::vector< T > const &vec)
Construct array copying from the given vector.
Definition immutable_array.hh:70
constexpr immutable_array() noexcept=default
Construct an empty array.
auto empty() const noexcept -> bool
Check if the array is empty.
Definition immutable_array.hh:123
auto data() const -> T const *
Get a pointer to the undelying data.
Definition immutable_array.hh:114
auto front() const -> const_reference
Get a reference to the first element.
Definition immutable_array.hh:108
typename vector_type::const_pointer const_pointer
The pointer type.
Definition immutable_array.hh:34
void swap(immutable_array &other) noexcept
Swap two immutable arrays.
Definition immutable_array.hh:129
friend auto operator==(immutable_array const &lhs, immutable_array const &rhs) -> bool
Compare two vectors.
Definition immutable_array.hh:132
typename vector_type::allocator_type allocator_type
The allocator type.
Definition immutable_array.hh:28
auto at(size_type pos) const -> const_reference
Get the element at the given index.
Definition immutable_array.hh:97
immutable_array(It first, It last)
Construct array coping from the given iterator range.
Definition immutable_array.hh:76
typename vector_type::difference_type difference_type
The signed size type.
Definition immutable_array.hh:32
auto size() const noexcept -> size_type
Get the size of the array.
Definition immutable_array.hh:126
auto back() const -> const_reference
Get a reference to the last element.
Definition immutable_array.hh:111
auto end() const noexcept -> const_iterator
Get an iterator pointing to the end of the array.
Definition immutable_array.hh:120
auto begin() const noexcept -> const_iterator
Get an iterator pointing to the beginning of the array.
Definition immutable_array.hh:117
immutable_array(It first, It last, Pred conv)
Construct array coping from the given iterator range.
Definition immutable_array.hh:83
auto make_immutable_array(Ts &&...args) -> immutable_array< T >
Construct an immutable array from the given elements.
Definition immutable_array.hh:162
void swap(immutable_array< T > &lhs, immutable_array< T > &rhs) noexcept
Swap two immutable arrays.
Definition immutable_array.hh:155
auto operator(const immutable_value< X > &lhs, const immutable_value< Y > &rhs)
Compare two immutable values.
Definition immutable_value.hh:152