Skip to content

Commit

Permalink
Assert for out-of-bounds subspans instead of throwing
Browse files Browse the repository at this point in the history
  • Loading branch information
kcat committed Mar 29, 2024
1 parent 5bc09d3 commit e95c370
Showing 1 changed file with 33 additions and 45 deletions.
78 changes: 33 additions & 45 deletions common/alspan.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,22 +220,22 @@ class span {
auto crend() const noexcept -> const_reverse_iterator { return cbegin(); }

template<std::size_t C>
[[nodiscard]] constexpr auto first() const -> span<element_type,C>
[[nodiscard]] constexpr auto first() const noexcept -> span<element_type,C>
{
static_assert(E >= C, "New size exceeds original capacity");
return span<element_type,C>{mData, C};
}

template<std::size_t C>
[[nodiscard]] constexpr auto last() const -> span<element_type,C>
[[nodiscard]] constexpr auto last() const noexcept -> span<element_type,C>
{
static_assert(E >= C, "New size exceeds original capacity");
return span<element_type,C>{mData+(E-C), C};
}

template<std::size_t O, std::size_t C>
[[nodiscard]] constexpr
auto subspan() const -> std::enable_if_t<C!=dynamic_extent,span<element_type,C>>
auto subspan() const noexcept -> std::enable_if_t<C!=dynamic_extent,span<element_type,C>>
{
static_assert(E >= O, "Offset exceeds extent");
static_assert(E-O >= C, "New size exceeds original capacity");
Expand All @@ -244,7 +244,7 @@ class span {

template<std::size_t O, std::size_t C=dynamic_extent>
[[nodiscard]] constexpr
auto subspan() const -> std::enable_if_t<C==dynamic_extent,span<element_type,E-O>>
auto subspan() const noexcept -> std::enable_if_t<C==dynamic_extent,span<element_type,E-O>>
{
static_assert(E >= O, "Offset exceeds extent");
return span<element_type,E-O>{mData+O, E-O};
Expand All @@ -254,12 +254,13 @@ class span {
* defining the specialization. As a result, these methods need to be
* defined later.
*/
[[nodiscard]] constexpr auto first(std::size_t count) const
-> span<element_type,dynamic_extent>;
[[nodiscard]] constexpr auto last(std::size_t count) const
[[nodiscard]] constexpr
auto first(std::size_t count) const noexcept -> span<element_type,dynamic_extent>;
[[nodiscard]] constexpr
auto last(std::size_t count) const noexcept -> span<element_type,dynamic_extent>;
[[nodiscard]] constexpr
auto subspan(std::size_t offset, std::size_t count=dynamic_extent) const noexcept
-> span<element_type,dynamic_extent>;
[[nodiscard]] constexpr auto subspan(std::size_t offset,
std::size_t count=dynamic_extent) const -> span<element_type,dynamic_extent>;

private:
pointer mData{nullptr};
Expand Down Expand Up @@ -343,64 +344,55 @@ class span<T,dynamic_extent> {
auto crend() const noexcept -> const_reverse_iterator { return cbegin(); }

template<std::size_t C>
[[nodiscard]] constexpr auto first() const -> span<element_type,C>
[[nodiscard]] constexpr auto first() const noexcept -> span<element_type,C>
{
if(C > mDataLength)
throw std::out_of_range{"Subspan count out of range"};
assert(C <= mDataLength);
return span<element_type,C>{mData, C};
}

[[nodiscard]] constexpr auto first(std::size_t count) const -> span
[[nodiscard]] constexpr auto first(std::size_t count) const noexcept -> span
{
if(count > mDataLength)
throw std::out_of_range{"Subspan count out of range"};
assert(count <= mDataLength);
return span{mData, count};
}

template<std::size_t C>
[[nodiscard]] constexpr auto last() const -> span<element_type,C>
[[nodiscard]] constexpr auto last() const noexcept -> span<element_type,C>
{
if(C > mDataLength)
throw std::out_of_range{"Subspan count out of range"};
assert(C <= mDataLength);
return span<element_type,C>{mData+mDataLength-C, C};
}

[[nodiscard]] constexpr auto last(std::size_t count) const -> span
[[nodiscard]] constexpr auto last(std::size_t count) const noexcept -> span
{
if(count > mDataLength)
throw std::out_of_range{"Subspan count out of range"};
assert(count <= mDataLength);
return span{mData+mDataLength-count, count};
}

template<std::size_t O, std::size_t C>
[[nodiscard]] constexpr
auto subspan() const -> std::enable_if_t<C!=dynamic_extent,span<element_type,C>>
auto subspan() const noexcept -> std::enable_if_t<C!=dynamic_extent,span<element_type,C>>
{
if(O > mDataLength)
throw std::out_of_range{"Subspan offset out of range"};
if(C > mDataLength-O)
throw std::out_of_range{"Subspan length out of range"};
assert(O <= mDataLength);
assert(C <= mDataLength-O);
return span<element_type,C>{mData+O, C};
}

template<std::size_t O, std::size_t C=dynamic_extent>
[[nodiscard]] constexpr
auto subspan() const -> std::enable_if_t<C==dynamic_extent,span<element_type,C>>
auto subspan() const noexcept -> std::enable_if_t<C==dynamic_extent,span<element_type,C>>
{
if(O > mDataLength)
throw std::out_of_range{"Subspan offset out of range"};
assert(O <= mDataLength);
return span<element_type,C>{mData+O, mDataLength-O};
}

[[nodiscard]] constexpr
auto subspan(std::size_t offset, std::size_t count=dynamic_extent) const -> span
auto subspan(std::size_t offset, std::size_t count=dynamic_extent) const noexcept -> span
{
if(offset > mDataLength)
throw std::out_of_range{"Subspan offset out of range"};
assert(offset <= mDataLength);
if(count != dynamic_extent)
{
if(count > mDataLength-offset)
throw std::out_of_range{"Subspan length out of range"};
assert(count <= mDataLength-offset);
return span{mData+offset, count};
}
return span{mData+offset, mDataLength-offset};
Expand All @@ -413,33 +405,29 @@ class span<T,dynamic_extent> {

template<typename T, std::size_t E>
[[nodiscard]] constexpr
auto span<T,E>::first(std::size_t count) const -> span<element_type,dynamic_extent>
auto span<T,E>::first(std::size_t count) const noexcept -> span<element_type,dynamic_extent>
{
if(count > size())
throw std::out_of_range{"Subspan count out of range"};
assert(count <= size());
return span<element_type>{mData, count};
}

template<typename T, std::size_t E>
[[nodiscard]] constexpr
auto span<T,E>::last(std::size_t count) const -> span<element_type,dynamic_extent>
auto span<T,E>::last(std::size_t count) const noexcept -> span<element_type,dynamic_extent>
{
if(count > size())
throw std::out_of_range{"Subspan count out of range"};
assert(count <= size());
return span<element_type>{mData+size()-count, count};
}

template<typename T, std::size_t E>
[[nodiscard]] constexpr
auto span<T,E>::subspan(std::size_t offset, std::size_t count) const
auto span<T,E>::subspan(std::size_t offset, std::size_t count) const noexcept
-> span<element_type,dynamic_extent>
{
if(offset > size())
throw std::out_of_range{"Subspan offset out of range"};
assert(offset <= size());
if(count != dynamic_extent)
{
if(count > size()-offset)
throw std::out_of_range{"Subspan length out of range"};
assert(count <= size()-offset);
return span<element_type>{mData+offset, count};
}
return span<element_type>{mData+offset, size()-offset};
Expand Down

0 comments on commit e95c370

Please sign in to comment.