pw_span: Update deduction guides

- Use the deduction guides specified in the C++20 draft standard.
- Expand tests to cover all deduction guides.

Change-Id: I9ab0c44b7bb1097c554c7e56f0b174b2615cacd3
diff --git a/pw_span/public/pw_span/span.h b/pw_span/public/pw_span/span.h
index 0f0fe08..423fd74 100644
--- a/pw_span/public/pw_span/span.h
+++ b/pw_span/public/pw_span/span.h
@@ -468,26 +468,22 @@
 }
 
 // Type-deducing helpers for constructing a span.
-// Pigweed: These are user-defined deduction guides instead of a make_span
-//          function.
-template <int&... ExplicitArgumentBarrier, typename T>
-span(T* data, size_t size)->span<T, dynamic_extent>;
+// Pigweed: Instead of a make_span function, provide the deduction guides
+//     specified in the C++20 standard.
+template <class T, std::size_t N>
+span(T (&)[N]) -> span<T, N>;
 
-template <int&... ExplicitArgumentBarrier, typename T>
-span(T* begin, T* end)->span<T, dynamic_extent>;
+template <class T, std::size_t N>
+span(std::array<T, N>&) -> span<T, N>;
 
-template <int&... ExplicitArgumentBarrier, typename Container>
-span(Container& container)
-    ->span<
-        std::remove_pointer_t<decltype(std::data(std::declval<Container>()))>,
-        span_internal::Extent<Container>::value>;
+template <class T, std::size_t N>
+span(const std::array<T, N>&) -> span<const T, N>;
 
-template <
-    typename Container,
-    typename T =
-        std::remove_pointer_t<decltype(std::data(std::declval<Container&>()))>,
-    typename = span_internal::EnableIfSpanCompatibleContainer<Container&, T>>
-span(Container& container)->span<T>;
+template <class Container>
+span(Container&) -> span<typename Container::value_type>;
+
+template <class Container>
+span(const Container&) -> span<const typename Container::value_type>;
 
 }  // namespace pw
 
diff --git a/pw_span/span_test.cc b/pw_span/span_test.cc
index 0e4a174..b9c70ec 100644
--- a/pw_span/span_test.cc
+++ b/pw_span/span_test.cc
@@ -56,6 +56,70 @@
 
 }  // namespace
 
+// Pigweed: Test deducing from std::string_view.
+TEST(SpanTest, DeductionGuides_MutableArray) {
+  char array[] = {'a', 'b', 'c', 'd', '\0'};
+
+  auto the_span = span(array);
+  static_assert(the_span.extent == 5u);
+  static_assert(the_span.size() == 5u);
+
+  the_span[0] = '!';
+  EXPECT_STREQ(the_span.data(), "!bcd");
+}
+
+TEST(SpanTest, DeductionGuides_ConstArray) {
+  static constexpr char array[] = {'a', 'b', 'c', 'd', '\0'};
+
+  constexpr auto the_span = span(array);
+  static_assert(the_span.extent == 5u);
+  static_assert(the_span.size() == 5u);
+
+  EXPECT_STREQ(the_span.data(), "abcd");
+}
+
+TEST(SpanTest, DeductionGuides_MutableStdArray) {
+  std::array<char, 5> array{'a', 'b', 'c', 'd'};
+
+  auto the_span = span(array);
+  static_assert(the_span.extent == 5u);
+  static_assert(the_span.size() == 5u);
+
+  the_span[0] = '?';
+  EXPECT_STREQ(the_span.data(), "?bcd");
+}
+
+TEST(SpanTest, DeductionGuides_ConstStdArray) {
+  static constexpr std::array<char, 5> array{'a', 'b', 'c', 'd'};
+
+  constexpr auto the_span = span(array);
+  static_assert(the_span.extent == 5u);
+  static_assert(the_span.size() == 5u);
+
+  EXPECT_STREQ(the_span.data(), "abcd");
+}
+
+TEST(SpanTest, DeductionGuides_MutableContainer) {
+  std::vector<int> foo = {3456};
+
+  auto the_span = span(foo);
+  static_assert(the_span.extent == dynamic_extent);
+
+  EXPECT_EQ(foo[0], the_span[0]);
+  EXPECT_EQ(foo.size(), the_span.size());
+
+  the_span[0] = 9876;
+  EXPECT_EQ(9876, foo[0]);
+}
+
+TEST(SpanTest, DeductionGuides_ConstContainer) {
+  auto the_span = span(std::string_view("Hello"));
+  static_assert(the_span.extent == dynamic_extent);
+
+  EXPECT_STREQ("Hello", the_span.data());
+  EXPECT_EQ(5u, the_span.size());
+}
+
 TEST(SpanTest, DefaultConstructor) {
   span<int> dynamic_span;
   EXPECT_EQ(nullptr, dynamic_span.data());
@@ -1009,9 +1073,10 @@
   static constexpr int kArray[] = {1, 6, 1, 8, 0};
   constexpr span<const int> span(kArray);
 
-  static_assert(constexpr_equal(std::begin(kArray), std::end(kArray),
-                                span.begin(), span.end()),
-                "");
+  static_assert(
+      constexpr_equal(
+          std::begin(kArray), std::end(kArray), span.begin(), span.end()),
+      "");
   static_assert(1 == span.begin()[0], "");
   // Pigweed: These tests assume an iterator object, but Pigweed's span uses a
   //          simple pointer.
@@ -1028,10 +1093,10 @@
   static constexpr int kArray[] = {1, 6, 1, 8, 0};
   constexpr span<const int> span(kArray);
 
-  EXPECT_TRUE(std::equal(std::rbegin(kArray), std::rend(kArray), span.rbegin(),
-                         span.rend()));
-  EXPECT_TRUE(std::equal(std::crbegin(kArray), std::crend(kArray),
-                         span.crbegin(), span.crend()));
+  EXPECT_TRUE(std::equal(
+      std::rbegin(kArray), std::rend(kArray), span.rbegin(), span.rend()));
+  EXPECT_TRUE(std::equal(
+      std::crbegin(kArray), std::crend(kArray), span.crbegin(), span.crend()));
 }
 
 // Pigweed: These are tests for make_span, which is not included in Pigweed's