Bug 1633350 - Add SplitAt method to mozilla::Span. r=hsivonen

Differential Revision: https://phabricator.services.mozilla.com/D72605
This commit is contained in:
Simon Giesecke 2020-04-27 11:16:30 +00:00
Родитель e8a20bbe1c
Коммит 46314aa8d2
2 изменённых файлов: 122 добавлений и 0 удалений

Просмотреть файл

@ -686,6 +686,22 @@ class Span {
return const_reverse_iterator{cbegin()}; return const_reverse_iterator{cbegin()};
} }
template <size_t SplitPoint>
constexpr std::pair<Span<ElementType, SplitPoint>,
Span<ElementType, Extent - SplitPoint>>
SplitAt() const {
static_assert(Extent != dynamic_extent);
static_assert(SplitPoint <= Extent);
return {First<SplitPoint>(), Last<Extent - SplitPoint>()};
}
constexpr std::pair<Span<ElementType, dynamic_extent>,
Span<ElementType, dynamic_extent>>
SplitAt(const index_type aSplitPoint) const {
MOZ_RELEASE_ASSERT(aSplitPoint <= Length());
return {First(aSplitPoint), Last(Length() - aSplitPoint)};
}
private: private:
// this implementation detail class lets us take advantage of the // this implementation detail class lets us take advantage of the
// empty base class optimization to pay for only storage of a single // empty base class optimization to pay for only storage of a single

Просмотреть файл

@ -2113,3 +2113,109 @@ SPAN_TEST(type_inference) {
static_assert(std::is_same_v<const Span<const int, 5>, decltype(s)>); static_assert(std::is_same_v<const Span<const int, 5>, decltype(s)>);
static_assert(arr == s.Elements()); static_assert(arr == s.Elements());
} }
SPAN_TEST(split_at_dynamic_with_dynamic_extent) {
static constexpr int arr[5] = {1, 2, 3, 4, 5};
constexpr Span<const int> s = Span{arr};
{ // Split at begin.
constexpr auto splitAt0Result = s.SplitAt(0);
static_assert(
std::is_same_v<Span<const int>, decltype(splitAt0Result.first)>);
static_assert(
std::is_same_v<Span<const int>, decltype(splitAt0Result.second)>);
ASSERT_EQ(s.Elements(), splitAt0Result.second.Elements());
ASSERT_EQ(0u, splitAt0Result.first.Length());
ASSERT_EQ(5u, splitAt0Result.second.Length());
}
{ // Split at end.
constexpr auto splitAt5Result = s.SplitAt(s.Length());
static_assert(
std::is_same_v<Span<const int>, decltype(splitAt5Result.first)>);
static_assert(
std::is_same_v<Span<const int>, decltype(splitAt5Result.second)>);
ASSERT_EQ(s.Elements(), splitAt5Result.first.Elements());
ASSERT_EQ(5u, splitAt5Result.first.Length());
ASSERT_EQ(0u, splitAt5Result.second.Length());
}
{
// Split inside.
constexpr auto splitAt3Result = s.SplitAt(3);
static_assert(
std::is_same_v<Span<const int>, decltype(splitAt3Result.first)>);
static_assert(
std::is_same_v<Span<const int>, decltype(splitAt3Result.second)>);
ASSERT_EQ(s.Elements(), splitAt3Result.first.Elements());
ASSERT_EQ(s.Elements() + 3, splitAt3Result.second.Elements());
ASSERT_EQ(3u, splitAt3Result.first.Length());
ASSERT_EQ(2u, splitAt3Result.second.Length());
}
}
SPAN_TEST(split_at_dynamic_with_static_extent) {
static constexpr int arr[5] = {1, 2, 3, 4, 5};
constexpr auto s = Span{arr};
{
// Split at begin.
constexpr auto splitAt0Result = s.SplitAt(0);
static_assert(
std::is_same_v<Span<const int>, decltype(splitAt0Result.first)>);
static_assert(
std::is_same_v<Span<const int>, decltype(splitAt0Result.second)>);
ASSERT_EQ(s.Elements(), splitAt0Result.second.Elements());
}
{
// Split at end.
constexpr auto splitAt5Result = s.SplitAt(s.Length());
static_assert(
std::is_same_v<Span<const int>, decltype(splitAt5Result.first)>);
static_assert(
std::is_same_v<Span<const int>, decltype(splitAt5Result.second)>);
ASSERT_EQ(s.Elements(), splitAt5Result.first.Elements());
}
{
// Split inside.
constexpr auto splitAt3Result = s.SplitAt(3);
static_assert(
std::is_same_v<Span<const int>, decltype(splitAt3Result.first)>);
static_assert(
std::is_same_v<Span<const int>, decltype(splitAt3Result.second)>);
ASSERT_EQ(s.Elements(), splitAt3Result.first.Elements());
ASSERT_EQ(s.Elements() + 3, splitAt3Result.second.Elements());
}
}
SPAN_TEST(split_at_static) {
static constexpr int arr[5] = {1, 2, 3, 4, 5};
constexpr auto s = Span{arr};
// Split at begin.
constexpr auto splitAt0Result = s.SplitAt<0>();
static_assert(
std::is_same_v<Span<const int, 0>, decltype(splitAt0Result.first)>);
static_assert(
std::is_same_v<Span<const int, 5>, decltype(splitAt0Result.second)>);
static_assert(splitAt0Result.second.Elements() == s.Elements());
// Split at end.
constexpr auto splitAt5Result = s.SplitAt<s.Length()>();
static_assert(std::is_same_v<Span<const int, s.Length()>,
decltype(splitAt5Result.first)>);
static_assert(
std::is_same_v<Span<const int, 0>, decltype(splitAt5Result.second)>);
static_assert(splitAt5Result.first.Elements() == s.Elements());
// Split inside.
constexpr auto splitAt3Result = s.SplitAt<3>();
static_assert(
std::is_same_v<Span<const int, 3>, decltype(splitAt3Result.first)>);
static_assert(
std::is_same_v<Span<const int, 2>, decltype(splitAt3Result.second)>);
static_assert(splitAt3Result.first.Elements() == s.Elements());
static_assert(splitAt3Result.second.Elements() == s.Elements() + 3);
}