Skip to content

Commit bc58f37

Browse files
committed
リファクタリング
1 parent e791fe8 commit bc58f37

2 files changed

Lines changed: 75 additions & 47 deletions

File tree

include/iris/run_length_sequence.hpp

Lines changed: 69 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ class run_length_sequence
9494
public:
9595
static_assert(!std::is_const_v<T>);
9696
static_assert(unsigned_numeric_integral<IndexT> && !std::is_const_v<IndexT>);
97+
static_assert(sizeof(IndexT) >= sizeof(int), "Small index type has no practical benefit");
9798
static_assert(!std::is_const_v<RunContainerT>);
9899

99100
using size_type = std::common_type_t<std::size_t, IndexT>;
@@ -103,7 +104,7 @@ class run_length_sequence
103104
{
104105
constexpr auto a = std::numeric_limits<IndexT>::max();
105106
constexpr auto b = std::numeric_limits<difference_type>::max();
106-
return std::cmp_less(b, a) ? b : a;
107+
return std::cmp_less(b, a) ? static_cast<size_type>(b) : static_cast<size_type>(a);
107108
}
108109

109110
private:
@@ -245,7 +246,7 @@ class run_length_sequence
245246

246247
[[nodiscard]] constexpr iterator begin() noexcept { check_range_concepts(); return iterator{std::ranges::begin(runs_), offsets_.begin()}; }
247248
[[nodiscard]] constexpr const_iterator begin() const noexcept { check_range_concepts(); return const_iterator{std::ranges::begin(runs_), offsets_.begin()}; }
248-
[[nodiscard]] constexpr const_iterator cbegin() const noexcept { check_range_concepts(); return begin(); }
249+
[[nodiscard]] constexpr const_iterator cbegin() const noexcept { return begin(); }
249250

250251
[[nodiscard]] constexpr iterator end() noexcept
251252
{
@@ -269,14 +270,14 @@ class run_length_sequence
269270
return const_iterator{std::ranges::end(runs_), std::prev(offsets_.end())};
270271
}
271272
}
272-
[[nodiscard]] constexpr const_iterator cend() const noexcept { check_range_concepts(); return end(); }
273+
[[nodiscard]] constexpr const_iterator cend() const noexcept { return end(); }
273274

274-
[[nodiscard]] constexpr reverse_iterator rbegin() noexcept { check_range_concepts(); return reverse_iterator{end()}; }
275-
[[nodiscard]] constexpr const_reverse_iterator rbegin() const noexcept { check_range_concepts(); return const_reverse_iterator{end()}; }
276-
[[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { check_range_concepts(); return rbegin(); }
277-
[[nodiscard]] constexpr reverse_iterator rend() noexcept { check_range_concepts(); return reverse_iterator{begin()}; }
278-
[[nodiscard]] constexpr const_reverse_iterator rend() const noexcept { check_range_concepts(); return const_reverse_iterator{begin()}; }
279-
[[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { check_range_concepts(); return rend(); }
275+
[[nodiscard]] constexpr reverse_iterator rbegin() noexcept { return reverse_iterator{end()}; }
276+
[[nodiscard]] constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator{end()}; }
277+
[[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
278+
[[nodiscard]] constexpr reverse_iterator rend() noexcept { return reverse_iterator{begin()}; }
279+
[[nodiscard]] constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator{begin()}; }
280+
[[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { return rend(); }
280281

281282
[[nodiscard]] constexpr bool empty() const noexcept
282283
{
@@ -294,7 +295,7 @@ class run_length_sequence
294295
return static_cast<size_type>(offsets_.back());
295296
}
296297

297-
[[nodiscard]] constexpr size_type segment_count() const noexcept
298+
[[nodiscard]] constexpr size_type run_count() const noexcept
298299
{
299300
static_assert(std::ranges::sized_range<RunContainerT>);
300301
return static_cast<size_type>(std::ranges::size(runs_));
@@ -310,43 +311,56 @@ class run_length_sequence
310311
}
311312

312313
template<class U>
313-
requires std::is_constructible_v<T, U>
314+
requires std::constructible_from<T, U> && req::half_equality_comparable<T, U>
314315
constexpr reference emplace_back(U&& value) IRIS_LIFETIMEBOUND
315316
{
316317
check_range_concepts();
317318
static_assert(std::equality_comparable<T>);
318-
319319
IRIS_ZZ_RUN_LENGTH_SEQUENCE_INVARIANT_GUARD
320320

321321
if (offsets_.empty()) {
322-
[[maybe_unused]] ofs_insertion_guard<true, true> ofs_insertion_guard{this};
323-
offsets_.emplace_back(static_cast<IndexT>(0u));
324-
offsets_.emplace_back(static_cast<IndexT>(1u)); // sentinel
322+
return this->emplace_back_on_empty(std::forward<U>(value));
323+
324+
} else {
325+
assert(!std::ranges::empty(runs_));
326+
assert(offsets_.size() >= 2);
327+
if (offsets_.back() == max_size()) {
328+
throwf<std::length_error>("run_length_sequence capacity exceeded");
329+
}
330+
331+
if (ranges::back(std::as_const(runs_)) == std::as_const(value)) {
332+
// Equivalent element already exists; no need to insert.
333+
return {offsets_.back()++, ranges::back(runs_)};
334+
}
335+
// Need to insert new element
336+
auto const new_pos = offsets_.back();
337+
offsets_.emplace_back(new_pos + static_cast<IndexT>(1u)); // new sentinel
338+
[[maybe_unused]] ofs_insertion_guard<true, false> ofs_insertion_guard{this};
325339
auto& elem = ranges::emplace_back_ref(runs_, std::forward<U>(value));
326340
ofs_insertion_guard.clear();
327-
return {static_cast<IndexT>(0u), elem};
341+
return {new_pos, elem};
342+
}
343+
}
344+
345+
template<class... Args>
346+
requires std::constructible_from<T, Args...>
347+
constexpr reference emplace_back(Args&&... args) IRIS_LIFETIMEBOUND
348+
{
349+
check_range_concepts();
350+
static_assert(std::equality_comparable<T>);
351+
IRIS_ZZ_RUN_LENGTH_SEQUENCE_INVARIANT_GUARD
352+
353+
if (offsets_.empty()) {
354+
return this->emplace_back_on_empty(std::forward<Args>(args)...);
328355

329356
} else {
330357
assert(!std::ranges::empty(runs_));
331358
assert(offsets_.size() >= 2);
332359
if (offsets_.back() == max_size()) {
333360
throwf<std::length_error>("run_length_sequence capacity exceeded");
334361
}
335-
if constexpr (req::half_equality_comparable<T, U>) {
336-
if (ranges::back(std::as_const(runs_)) == std::as_const(value)) {
337-
// Equivalent element already exists; no need to insert.
338-
return {offsets_.back()++, ranges::back(runs_)};
339-
}
340-
// Need to insert new element
341-
auto const new_pos = offsets_.back();
342-
offsets_.emplace_back(new_pos + static_cast<IndexT>(1u)); // new sentinel
343-
[[maybe_unused]] ofs_insertion_guard<true, false> ofs_insertion_guard{this};
344-
auto& elem = ranges::emplace_back_ref(runs_, std::forward<U>(value));
345-
ofs_insertion_guard.clear();
346-
return {new_pos, elem};
347-
348-
} else if constexpr (requires { ranges::weak_pop_back(runs_); }) {
349-
auto& elem = ranges::emplace_back_ref(runs_, std::forward<U>(value));
362+
if constexpr (requires { ranges::weak_pop_back(runs_); }) {
363+
auto& elem = ranges::emplace_back_ref(runs_, std::forward<Args>(args)...);
350364
[[maybe_unused]] elem_insertion_guard<true> elem_insertion_guard{this};
351365

352366
auto const prev_it = std::ranges::prev(std::ranges::end(runs_), 2);
@@ -365,7 +379,7 @@ class run_length_sequence
365379
return {new_pos, elem};
366380

367381
} else {
368-
T temp(std::forward<U>(value));
382+
T temp(std::forward<Args>(args)...);
369383
if (ranges::back(std::as_const(runs_)) == std::as_const(temp)) {
370384
// Equivalent element already exists; no need to insert.
371385
return {offsets_.back()++, ranges::back(runs_)};
@@ -382,7 +396,7 @@ class run_length_sequence
382396
}
383397

384398
private:
385-
constexpr void check_range_concepts() const noexcept
399+
static constexpr void check_range_concepts() noexcept
386400
{
387401
static_assert(std::ranges::bidirectional_range<RunContainerT>);
388402
static_assert(std::same_as<std::ranges::range_value_t<RunContainerT>, T>);
@@ -395,6 +409,18 @@ class run_length_sequence
395409
});
396410
}
397411

412+
template<class... Args>
413+
constexpr reference emplace_back_on_empty(Args&&... args) IRIS_LIFETIMEBOUND
414+
{
415+
assert(this->empty());
416+
[[maybe_unused]] ofs_insertion_guard<true, true> ofs_insertion_guard{this};
417+
offsets_.emplace_back(static_cast<IndexT>(0u));
418+
offsets_.emplace_back(static_cast<IndexT>(1u)); // sentinel
419+
auto& elem = ranges::emplace_back_ref(runs_, std::forward<Args>(args)...);
420+
ofs_insertion_guard.clear();
421+
return {static_cast<IndexT>(0u), elem};
422+
}
423+
398424
template<bool IsBack, bool WasEmpty>
399425
struct [[nodiscard]] ofs_insertion_guard
400426
{
@@ -464,15 +490,17 @@ class run_length_sequence
464490

465491
constexpr ~check_invariant_guard() noexcept
466492
{
467-
if (self_->offsets_.empty()) {
468-
assert(std::ranges::empty(self_->runs_));
469-
} else {
470-
assert(self_->offsets_.size() == std::ranges::size(self_->runs_) + 1);
471-
assert(self_->offsets_[0] == 0);
472-
for (std::size_t i = 0; i < self_->offsets_.size() - 1; ++i) {
473-
assert(self_->offsets_[i] < self_->offsets_[i + 1]);
474-
}
493+
auto const& offsets = self_->offsets_;
494+
auto const& runs = self_->runs_;
495+
if (offsets.empty()) {
496+
assert(std::ranges::empty(runs));
497+
return;
475498
}
499+
assert(offsets.size() >= 2);
500+
assert(offsets.size() == std::ranges::size(runs) + 1);
501+
assert(offsets.front() == static_cast<IndexT>(0u));
502+
auto const n = offsets.size();
503+
assert(offsets[n - 2] < offsets[n - 1]);
476504
}
477505

478506
private:

test/run_length_sequence.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ TEST_CASE("run_length_sequence")
7171
{
7272
auto&& elem = seq.emplace_back(1.0);
7373
REQUIRE(seq.size() == 1);
74-
REQUIRE(seq.segment_count() == 1);
74+
REQUIRE(seq.run_count() == 1);
7575
CHECK(elem.index == 0);
7676
CHECK(elem.value == 1.0);
7777

@@ -87,7 +87,7 @@ TEST_CASE("run_length_sequence")
8787
{
8888
auto&& elem = seq.emplace_back(1.0);
8989
REQUIRE(seq.size() == 2);
90-
REQUIRE(seq.segment_count() == 1);
90+
REQUIRE(seq.run_count() == 1);
9191
CHECK(elem.index == 1);
9292
CHECK(elem.value == 1.0);
9393

@@ -108,7 +108,7 @@ TEST_CASE("run_length_sequence")
108108
{
109109
auto&& elem = seq.emplace_back(1.1);
110110
REQUIRE(seq.size() == 3);
111-
REQUIRE(seq.segment_count() == 2);
111+
REQUIRE(seq.run_count() == 2);
112112
CHECK(elem.index == 2);
113113
CHECK(elem.value == 1.1);
114114

@@ -134,7 +134,7 @@ TEST_CASE("run_length_sequence")
134134
{
135135
auto&& elem = seq.emplace_back(1.1);
136136
REQUIRE(seq.size() == 4);
137-
REQUIRE(seq.segment_count() == 2);
137+
REQUIRE(seq.run_count() == 2);
138138
CHECK(elem.index == 3);
139139
CHECK(elem.value == 1.1);
140140

@@ -165,7 +165,7 @@ TEST_CASE("run_length_sequence")
165165
{
166166
auto&& elem = seq.emplace_back(1.1);
167167
REQUIRE(seq.size() == 5);
168-
REQUIRE(seq.segment_count() == 2);
168+
REQUIRE(seq.run_count() == 2);
169169
CHECK(elem.index == 4);
170170
CHECK(elem.value == 1.1);
171171

@@ -201,7 +201,7 @@ TEST_CASE("run_length_sequence")
201201
{
202202
auto&& elem = seq.emplace_back(1.2);
203203
REQUIRE(seq.size() == 6);
204-
REQUIRE(seq.segment_count() == 3);
204+
REQUIRE(seq.run_count() == 3);
205205
CHECK(elem.index == 5);
206206
CHECK(elem.value == 1.2);
207207

0 commit comments

Comments
 (0)