summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Girts <girtsf@users.noreply.github.com>2019-03-08 12:05:39 -0800
committerGravatar Derek Mauro <761129+derekmauro@users.noreply.github.com>2019-03-08 15:05:39 -0500
commitc1cecb25a94c075725e9d2640f6b978a8f61957b (patch)
tree505c35368522ebe4e6717b73f6c24e1279c5c173
parent38b704384cd2f17590b3922b97744be0b43622c9 (diff)
Implement Span::first and Span::last from C++20 (#274)
This implements `first` and `last` methods on `Span` that mimics ones in `std::span`.
-rw-r--r--absl/types/span.h34
-rw-r--r--absl/types/span_test.cc34
2 files changed, 68 insertions, 0 deletions
diff --git a/absl/types/span.h b/absl/types/span.h
index bce18ebc..ea1808d3 100644
--- a/absl/types/span.h
+++ b/absl/types/span.h
@@ -485,6 +485,40 @@ class Span {
: (base_internal::ThrowStdOutOfRange("pos > size()"), Span());
}
+ // Span::first()
+ //
+ // Returns a `Span` containing first `len` elements. Parameter `len` is of
+ // type `size_type` and thus non-negative. `len` value must be <= size().
+ //
+ // Examples:
+ //
+ // std::vector<int> vec = {10, 11, 12, 13};
+ // absl::MakeSpan(vec).first(1); // {10}
+ // absl::MakeSpan(vec).first(3); // {10, 11, 12}
+ // absl::MakeSpan(vec).first(5); // throws std::out_of_range
+ constexpr Span first(size_type len) const {
+ return (len <= size())
+ ? Span(data(), len)
+ : (base_internal::ThrowStdOutOfRange("len > size()"), Span());
+ }
+
+ // Span::last()
+ //
+ // Returns a `Span` containing last `len` elements. Parameter `len` is of
+ // type `size_type` and thus non-negative. `len` value must be <= size().
+ //
+ // Examples:
+ //
+ // std::vector<int> vec = {10, 11, 12, 13};
+ // absl::MakeSpan(vec).last(1); // {13}
+ // absl::MakeSpan(vec).last(3); // {11, 12, 13}
+ // absl::MakeSpan(vec).last(5); // throws std::out_of_range
+ constexpr Span last(size_type len) const {
+ return (len <= size())
+ ? Span(data() + size() - len, len)
+ : (base_internal::ThrowStdOutOfRange("len > size()"), Span());
+ }
+
// Support for absl::Hash.
template <typename H>
friend H AbslHashValue(H h, Span v) {
diff --git a/absl/types/span_test.cc b/absl/types/span_test.cc
index 294229ea..9269f911 100644
--- a/absl/types/span_test.cc
+++ b/absl/types/span_test.cc
@@ -295,6 +295,38 @@ TEST(IntSpan, Subspan) {
#endif
}
+TEST(IntSpan, First) {
+ std::vector<int> empty;
+ EXPECT_THAT(absl::MakeSpan(empty).first(0), SpanIs(empty));
+
+ auto ramp = MakeRamp(10);
+ EXPECT_THAT(absl::MakeSpan(ramp).first(0), SpanIs(ramp.data(), 0));
+ EXPECT_THAT(absl::MakeSpan(ramp).first(10), SpanIs(ramp));
+ EXPECT_THAT(absl::MakeSpan(ramp).first(3), SpanIs(ramp.data(), 3));
+
+#ifdef ABSL_HAVE_EXCEPTIONS
+ EXPECT_THROW(absl::MakeSpan(ramp).first(11), std::out_of_range);
+#else
+ EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).first(11), "");
+#endif
+}
+
+TEST(IntSpan, Last) {
+ std::vector<int> empty;
+ EXPECT_THAT(absl::MakeSpan(empty).last(0), SpanIs(empty));
+
+ auto ramp = MakeRamp(10);
+ EXPECT_THAT(absl::MakeSpan(ramp).last(0), SpanIs(ramp.data() + 10, 0));
+ EXPECT_THAT(absl::MakeSpan(ramp).last(10), SpanIs(ramp));
+ EXPECT_THAT(absl::MakeSpan(ramp).last(3), SpanIs(ramp.data() + 7, 3));
+
+#ifdef ABSL_HAVE_EXCEPTIONS
+ EXPECT_THROW(absl::MakeSpan(ramp).last(11), std::out_of_range);
+#else
+ EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).last(11), "");
+#endif
+}
+
TEST(IntSpan, MakeSpanPtrLength) {
std::vector<int> empty;
auto s_empty = absl::MakeSpan(empty.data(), empty.size());
@@ -769,6 +801,8 @@ TEST(ConstIntSpan, ConstexprTest) {
ABSL_TEST_CONSTEXPR(span.begin());
ABSL_TEST_CONSTEXPR(span.cbegin());
ABSL_TEST_CONSTEXPR(span.subspan(0, 0));
+ ABSL_TEST_CONSTEXPR(span.first(1));
+ ABSL_TEST_CONSTEXPR(span.last(1));
ABSL_TEST_CONSTEXPR(span[0]);
}