Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions include/iris/error/throwf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ inline namespace error_functions {
// critical paths as some compilers fail to optimize the plain `throw` statement
// even though the statement itself should imply `[[noreturn]]`.
template<class E>
requires std::is_default_constructible_v<E>
IRIS_CONFIG_THROW_NORETURN void throwf()
{
static_assert(std::is_base_of_v<std::exception, E>);
static_assert(std::is_constructible_v<E>);
IRIS_CONFIG_THROW_IMPL(E{});
IRIS_CONFIG_THROW_IMPL(E());
}

// This function can be used to strongly assume optimization in some performance-
Expand All @@ -40,7 +41,7 @@ IRIS_CONFIG_THROW_NORETURN void throwf(Arg&& arg, Rest&&... rest)
{
static_assert(std::is_base_of_v<std::exception, E>);
static_assert(!std::is_base_of_v<std::exception, std::remove_cvref_t<Arg>>, "don't copy/move construct exception types directly");
IRIS_CONFIG_THROW_IMPL(E{std::forward<Arg>(arg), std::forward<Rest>(rest)...});
IRIS_CONFIG_THROW_IMPL(E(std::forward<Arg>(arg), std::forward<Rest>(rest)...));
}

} // error_functions
Expand Down
8 changes: 4 additions & 4 deletions include/iris/error/throwf_format.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ template<class E, class... Args>
IRIS_CONFIG_THROW_NORETURN void throwf(std::format_string<Args...> fmt, Args&&... args)
{
static_assert(std::is_base_of_v<std::exception, E>);
IRIS_CONFIG_THROW_IMPL(E{std::format(std::move(fmt), std::forward<Args>(args)...)});
IRIS_CONFIG_THROW_IMPL(E(std::format(std::move(fmt), std::forward<Args>(args)...)));
}

template<class E, NotStringLike Arg0, class... Args>
requires detail::constructible_from_string_like_types<E, Arg0>
IRIS_CONFIG_THROW_NORETURN void throwf(Arg0&& arg0, std::format_string<Args...> fmt, Args&&... args)
{
static_assert(std::is_base_of_v<std::exception, E>);
IRIS_CONFIG_THROW_IMPL(E{std::forward<Arg0>(arg0), std::format(std::move(fmt), std::forward<Args>(args)...)});
IRIS_CONFIG_THROW_IMPL(E(std::forward<Arg0>(arg0), std::format(std::move(fmt), std::forward<Args>(args)...)));
}

template<class E, NotStringLike Arg0, NotStringLike Arg1, class... Args>
Expand All @@ -50,10 +50,10 @@ IRIS_CONFIG_THROW_NORETURN void throwf(Arg0&& arg0, Arg1&& arg1, std::format_str
{
static_assert(std::is_base_of_v<std::exception, E>);
IRIS_CONFIG_THROW_IMPL(
E{
E(
std::forward<Arg0>(arg0), std::forward<Arg1>(arg1),
std::format(std::move(fmt), std::forward<Args>(args)...)
}
)
);
}

Expand Down
100 changes: 100 additions & 0 deletions include/iris/run_length_sequence.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <iris/requirements.hpp>
#include <iris/type_traits.hpp>

#include <functional>
#include <algorithm>
#include <vector>
#include <ranges>
Expand Down Expand Up @@ -145,6 +146,23 @@ class run_length_sequence
return {index(), *value_it_};
}

[[nodiscard]] constexpr T const& run_value() const noexcept
{
return *value_it_;
}

constexpr void advance_run() noexcept
{
++ofs_it_;
++value_it_;
rel_pos_ = static_cast<IndexT>(0u);
}
[[nodiscard]] friend constexpr iterator_impl next_run(iterator_impl it) noexcept
{
it.advance_run();
return it;
}

constexpr iterator_impl& operator++() noexcept
{
auto ofs_next = std::next(ofs_it_);
Expand Down Expand Up @@ -469,6 +487,88 @@ class run_length_sequence
);
}

template<class Pred>
requires std::predicate<Pred&, T const&>
[[nodiscard]] constexpr const_iterator find_run_if(const_iterator from, Pred&& pred) const
noexcept(std::is_nothrow_invocable_v<Pred&, T const&>)
{
auto const last = this->end();
for (; from != last; from.advance_run()) {
if (std::invoke(pred, from.run_value())) {
return from;
}
}
return last;
}

template<class Pred>
requires std::predicate<Pred&, T const&>
[[nodiscard]] constexpr const_iterator find_run_if_not(const_iterator from, Pred&& pred) const
noexcept(std::is_nothrow_invocable_v<Pred&, T const&>)
{
auto const last = this->end();
for (; from != last; from.advance_run()) {
if (!std::invoke(pred, from.run_value())) {
return from;
}
}
return last;
}

template<class U>
requires req::half_equality_comparable<T, U>
[[nodiscard]] constexpr const_iterator find_run(const_iterator from, U const& value) const
noexcept(noexcept(std::declval<T const&>() == value))
{
return this->find_run_if(std::move(from), [&](T const& e) noexcept(noexcept(e == value)) {
return e == value;
});
}

template<class U>
requires req::half_equality_comparable<T, U>
[[nodiscard]] constexpr const_iterator find_run_not(const_iterator from, U const& value) const
noexcept(noexcept(std::declval<T const&>() != value))
{
return this->find_run_if(std::move(from), [&](T const& e) noexcept(noexcept(e != value)) {
return e != value;
});
}

// ---------------------------------------------------------------------

template<class Pred>
requires std::predicate<Pred&, T const&>
[[nodiscard]] constexpr const_iterator find_run_if(Pred&& pred) const
noexcept(noexcept(this->find_run_if(begin(), std::forward<Pred>(pred))))
{
return this->find_run_if(begin(), std::forward<Pred>(pred));
}

template<class Pred>
requires std::predicate<Pred&, T const&>
[[nodiscard]] constexpr const_iterator find_run_if_not(Pred&& pred) const
noexcept(noexcept(this->find_run_if_not(begin(), std::forward<Pred>(pred))))
{
return this->find_run_if_not(begin(), std::forward<Pred>(pred));
}

template<class U>
requires req::half_equality_comparable<T, U>
[[nodiscard]] constexpr const_iterator find_run(U const& value) const
noexcept(noexcept(this->find_run(begin(), value)))
{
return this->find_run(begin(), value);
}

template<class U>
requires req::half_equality_comparable<T, U>
[[nodiscard]] constexpr const_iterator find_run_not(U const& value) const
noexcept(noexcept(this->find_run_not(begin(), value)))
{
return this->find_run_not(begin(), value);
}

// ---------------------------------------------------------------------

// Returns an iterator to the element at logical position `pos`, or `end()`
Expand Down
Loading