libstdc++: Fix deduction guide for std::span (PR93426)
authorJonathan Wakely <jwakely@redhat.com>
Mon, 27 Jan 2020 10:30:03 +0000 (10:30 +0000)
committerJonathan Wakely <jwakely@redhat.com>
Mon, 27 Jan 2020 10:55:19 +0000 (10:55 +0000)
The deduction guide from an iterator and sentinel used the wrong alias
template and so didn't work.

PR libstdc++/93426
* include/std/span (span): Fix deduction guide.
* testsuite/23_containers/span/deduction.cc: New test.

libstdc++-v3/ChangeLog
libstdc++-v3/include/std/span
libstdc++-v3/testsuite/23_containers/span/deduction.cc [new file with mode: 0644]

index 0067e581acb83a05638464150b9519d27f969ad3..2b877a8b44df4f2569766e1d9a9646a0803d9815 100644 (file)
@@ -1,3 +1,9 @@
+2020-01-27  Jonathan Wakely  <jwakely@redhat.com>
+
+       PR libstdc++/93426
+       * include/std/span (span): Fix deduction guide.
+       * testsuite/23_containers/span/deduction.cc: New test.
+
 2020-01-24  Jonathan Wakely  <jwakely@redhat.com>
 
        * libsupc++/compare (__cmp_cat::_Eq): Remove enumeration type.
index 0dae18672aff3986909cadd195b62530b24c99d2..0072010dea8f7b537a166f8825bf6b6b0c46ac94 100644 (file)
@@ -190,7 +190,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        : span(static_cast<pointer>(__arr.data()), _ArrayExtent)
        { }
 
-    public:
       template<ranges::contiguous_range _Range>
        requires (_Extent == dynamic_extent)
          && (!__detail::__is_std_span<remove_cvref_t<_Range>>::value)
@@ -404,6 +403,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     };
 
   // deduction guides
+
   template<typename _Type, size_t _ArrayExtent>
     span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>;
 
@@ -416,7 +416,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<contiguous_iterator _Iter, typename _Sentinel>
     span(_Iter, _Sentinel)
-      -> span<remove_reference_t<ranges::range_reference_t<_Iter>>>;
+      -> span<remove_reference_t<iter_reference_t<_Iter>>>;
 
   template<typename _Range>
     span(_Range &&)
diff --git a/libstdc++-v3/testsuite/23_containers/span/deduction.cc b/libstdc++-v3/testsuite/23_containers/span/deduction.cc
new file mode 100644 (file)
index 0000000..66e955e
--- /dev/null
@@ -0,0 +1,84 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <span>
+
+template<typename T, int N, typename U>
+constexpr bool is_static_span(const U&)
+{
+  return std::is_same_v<std::span<T, N>, U> && N != std::dynamic_extent;
+}
+
+template<typename T, typename U>
+constexpr bool is_dynamic_span(const U&)
+{
+  return std::is_same_v<std::span<T>, U>;
+}
+
+struct Range
+{
+  float* begin() const;
+  float* end() const;
+};
+
+void
+test01()
+{
+  const char c[] = "";
+  int i[2]{};
+  std::array<long, 3> a;
+  Range r;
+
+  std::span s1(c);
+  static_assert( is_static_span<const char, 1>(s1) );
+
+  std::span s2(i);
+  static_assert( is_static_span<int, 2>(s2) );
+
+  std::span s3(a);
+  static_assert( is_static_span<long, 3>(s3) );
+
+  std::span s4(const_cast<const std::array<long, 3>&>(a));
+  static_assert( is_static_span<const long, 3>(s4) );
+
+  std::span s5(std::begin(i), std::end(i));
+  static_assert( is_dynamic_span<int>(s5) );
+
+  std::span s6(std::cbegin(i), std::cend(i));
+  static_assert( is_dynamic_span<const int>(s6) );
+
+  std::span s7(r);
+  static_assert( is_dynamic_span<float>(s7) );
+
+  std::span s8(s1);
+  static_assert( is_static_span<const char, 1>(s8) );
+
+  std::span s9(s2);
+  static_assert( is_static_span<int, 2>(s9) );
+
+  std::span s10(const_cast<std::span<int, 2>&>(s2));
+  static_assert( is_static_span<int, 2>(s10) );
+
+  std::span s11(s5);
+  static_assert( is_dynamic_span<int>(s11) );
+
+  std::span s12(const_cast<const std::span<int>&>(s5));
+  static_assert( is_dynamic_span<int>(s12) );
+}