Implement Span::first and Span::last from C++20 (#274)
This implements `first` and `last` methods on `Span` that mimics ones in `std::span`.
This commit is contained in:
		
							parent
							
								
									38b704384c
								
							
						
					
					
						commit
						c1cecb25a9
					
				
					 2 changed files with 68 additions and 0 deletions
				
			
		|  | @ -485,6 +485,40 @@ class Span { | ||||||
|                : (base_internal::ThrowStdOutOfRange("pos > size()"), 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.
 |   // Support for absl::Hash.
 | ||||||
|   template <typename H> |   template <typename H> | ||||||
|   friend H AbslHashValue(H h, Span v) { |   friend H AbslHashValue(H h, Span v) { | ||||||
|  |  | ||||||
|  | @ -295,6 +295,38 @@ TEST(IntSpan, Subspan) { | ||||||
| #endif | #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) { | TEST(IntSpan, MakeSpanPtrLength) { | ||||||
|   std::vector<int> empty; |   std::vector<int> empty; | ||||||
|   auto s_empty = absl::MakeSpan(empty.data(), empty.size()); |   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.begin()); | ||||||
|   ABSL_TEST_CONSTEXPR(span.cbegin()); |   ABSL_TEST_CONSTEXPR(span.cbegin()); | ||||||
|   ABSL_TEST_CONSTEXPR(span.subspan(0, 0)); |   ABSL_TEST_CONSTEXPR(span.subspan(0, 0)); | ||||||
|  |   ABSL_TEST_CONSTEXPR(span.first(1)); | ||||||
|  |   ABSL_TEST_CONSTEXPR(span.last(1)); | ||||||
|   ABSL_TEST_CONSTEXPR(span[0]); |   ABSL_TEST_CONSTEXPR(span[0]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue