libstdc++: Fix deduction guide for std::span (PR93426)

Message ID 20200127105906.GA31025@redhat.com
State New
Headers show
Series
  • libstdc++: Fix deduction guide for std::span (PR93426)
Related show

Commit Message

Jonathan Wakely Jan. 27, 2020, 10:59 a.m.
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.

This used to work correctly but regressed with r279000.

Tested powerpc64le-linux, committed to trunk.
commit 389cd88ce797e2a4345eab8db478a3b8eba798e8
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Jan 27 10:30:03 2020 +0000

    libstdc++: Fix deduction guide for std::span (PR93426)
    
    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.

Patch

diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span
index 0dae18672af..0072010dea8 100644
--- a/libstdc++-v3/include/std/span
+++ b/libstdc++-v3/include/std/span
@@ -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
index 00000000000..66e955e961b
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/span/deduction.cc
@@ -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) );
+}