public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Implement LWG 3255 for std::span constructors
@ 2019-09-30 11:51 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2019-09-30 11:51 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 680 bytes --]

Also fix the constraints on span(Container&) and span(const Container&)
constructors so that they aren't used for const spans or const arrays.

	* include/std/span (span(element_type(&)[N]))
	(span(array<value_type, N>&), span(const array<value_type, N>&)):
	Deduce array element type to allow safe const conversions (LWG 3255).
	[!_GLIBCXX_P1394] (span(Container&), span(const Container&)): Use
	remove_cv_t on arguments to __is_std_span and __is_std_array.
	* testsuite/23_containers/span/lwg3255.cc: New test.

This library issue hasn't been resolved yet, but the proposed
resolution looks right and so I'm implementing it now.

Tested powerpc64le-linux, committed to trunk.



[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 7932 bytes --]

commit f7686704e7edb8b38b4d4726726b97b78ae2da8d
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Sep 30 11:48:14 2019 +0100

    Implement LWG 3255 for std::span constructors
    
    Also fix the constraints on span(Container&) and span(const Container&)
    constructors so that they aren't used for const spans or const arrays.
    
            * include/std/span (span(element_type(&)[N]))
            (span(array<value_type, N>&), span(const array<value_type, N>&)):
            Deduce array element type to allow safe const conversions (LWG 3255).
            [!_GLIBCXX_P1394] (span(Container&), span(const Container&)): Use
            remove_cv_t on arguments to __is_std_span and __is_std_array.
            * testsuite/23_containers/span/lwg3255.cc: New test.

diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span
index 1a0d61c1947..fcec22a6c57 100644
--- a/libstdc++-v3/include/std/span
+++ b/libstdc++-v3/include/std/span
@@ -125,6 +125,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       template<typename _Tp>
 	using __is_compatible = is_convertible<_Tp(*)[], _Type(*)[]>;
 
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 3255. span's array constructor is too strict
+      template<typename _Tp, size_t _ArrayExtent,
+	       typename = enable_if_t<_Extent == dynamic_extent
+				      || _ArrayExtent == _Extent>>
+	using __is_compatible_array  = __is_compatible<_Tp>;
+
     public:
       // member types
       using value_type             = remove_cv_t<_Type>;
@@ -149,9 +156,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       // constructors
 
-      template <typename _Dummy = _Type,
-		enable_if_t<is_same_v<_Dummy, _Type>
-		  && (_Extent == dynamic_extent || _Extent == 0)>* = nullptr>
+      template<bool _DefaultConstructible = (_Extent + 1u) <= 1u,
+	       enable_if_t<_DefaultConstructible>* = nullptr>
 	constexpr
 	span() noexcept : _M_extent(0), _M_ptr(nullptr)
 	{ }
@@ -159,28 +165,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr
       span(const span&) noexcept = default;
 
-      template<size_t _ArrayExtent,
-	enable_if_t<_Extent == dynamic_extent || _ArrayExtent == _Extent>*
-	  = nullptr>
+      template<typename _Tp, size_t _ArrayExtent,
+	       typename = _Require<__is_compatible_array<_Tp, _ArrayExtent>>>
 	constexpr
-	span(element_type (&__arr)[_ArrayExtent]) noexcept
+	span(_Tp (&__arr)[_ArrayExtent]) noexcept
 	: span(static_cast<pointer>(__arr), _ArrayExtent)
 	{ }
 
-      template<size_t _ArrayExtent,
-	enable_if_t<_Extent == dynamic_extent || _ArrayExtent == _Extent>*
-	  = nullptr>
+      template<typename _Tp, size_t _ArrayExtent,
+	       typename = _Require<__is_compatible_array<_Tp, _ArrayExtent>>>
 	constexpr
-	span(array<value_type, _ArrayExtent>& __arr) noexcept
-	: span(__arr.data(), _ArrayExtent)
+	span(array<_Tp, _ArrayExtent>& __arr) noexcept
+	: span(static_cast<pointer>(__arr.data()), _ArrayExtent)
 	{ }
 
-      template<size_t _ArrayExtent,
-	enable_if_t<_Extent == dynamic_extent || _ArrayExtent == _Extent>*
-	  = nullptr>
+      template<typename _Tp, size_t _ArrayExtent,
+	       typename = _Require<__is_compatible_array<_Tp, _ArrayExtent>>>
 	constexpr
-	span(const array<value_type, _ArrayExtent>& __arr) noexcept
-	: span(__arr.data(), _ArrayExtent)
+	span(const array<_Tp, _ArrayExtent>& __arr) noexcept
+	: span(static_cast<pointer>(__arr.data()), _ArrayExtent)
 	{ }
 
       // NOTE: when the time comes, and P1394 -
@@ -271,8 +274,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     public:
       template<typename _Container, typename = _Require<
 		bool_constant<_Extent == dynamic_extent>,
-		__not_<__detail::__is_std_span<_Container>>,
-		__not_<__detail::__is_std_array<_Container>>,
+		__not_<__detail::__is_std_span<remove_cv_t<_Container>>>,
+		__not_<__detail::__is_std_array<remove_cv_t<_Container>>>,
 		__not_<is_array<_Container>>,
 		__is_compatible_container<_Container>>>
 	constexpr
@@ -283,8 +286,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       template<typename _Container, typename = _Require<
 		bool_constant<_Extent == dynamic_extent>,
-		__not_<__detail::__is_std_span<_Container>>,
-		__not_<__detail::__is_std_array<_Container>>,
+		__not_<__detail::__is_std_span<remove_cv_t<_Container>>>,
+		__not_<__detail::__is_std_array<remove_cv_t<_Container>>>,
 		__not_<is_array<_Container>>,
 		__is_compatible_container<const _Container>>>
 	constexpr
diff --git a/libstdc++-v3/testsuite/23_containers/span/lwg3255.cc b/libstdc++-v3/testsuite/23_containers/span/lwg3255.cc
new file mode 100644
index 00000000000..638c88101f9
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/span/lwg3255.cc
@@ -0,0 +1,69 @@
+// Copyright (C) 2019 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>
+#include <array>
+
+using std::span;
+using std::dynamic_extent;
+using std::array;
+using std::is_constructible_v;
+
+// LWG 3255 span's array constructor is too strict
+
+// FIXME: remove '!' from next line when P0388R4 is implemented:
+static_assert( ! is_constructible_v<span<const int* const>, array<int*, 2>> );
+static_assert( is_constructible_v<span<const int>, array<const int, 4>> );
+
+static_assert( is_constructible_v<span<int, 1>, int(&)[1]> );
+static_assert( is_constructible_v<span<const int, 1>, int(&)[1]> );
+static_assert( is_constructible_v<span<const int, 1>, const int(&)[1]> );
+
+static_assert( is_constructible_v<span<int, 1>, array<int, 1>&> );
+static_assert( is_constructible_v<span<const int, 1>, array<int, 1>&> );
+static_assert( is_constructible_v<span<const int, 1>, array<const int, 1>&> );
+
+static_assert( is_constructible_v<span<int, 1>, const array<int, 1>&> );
+static_assert( is_constructible_v<span<const int, 1>, const array<int, 1>&> );
+static_assert( is_constructible_v<span<const int, 1>, const array<const int, 1>&> );
+
+static_assert( !is_constructible_v<span<int, 1>, int(&)[2]> );
+static_assert( !is_constructible_v<span<const int, 1>, int(&)[2]> );
+static_assert( !is_constructible_v<span<const int, 1>, const int(&)[2]> );
+
+static_assert( !is_constructible_v<span<int, 1>, array<int, 2>&> );
+static_assert( !is_constructible_v<span<const int, 1>, array<int, 2>&> );
+static_assert( !is_constructible_v<span<const int, 1>, array<const int, 2>&> );
+
+static_assert( !is_constructible_v<span<int, 1>, const array<int, 2>&> );
+static_assert( !is_constructible_v<span<const int, 1>, const array<int, 2>&> );
+static_assert( !is_constructible_v<span<const int, 1>, const array<const int, 2>&> );
+
+static_assert( is_constructible_v<span<int>, int(&)[2]> );
+static_assert( is_constructible_v<span<const int>, int(&)[2]> );
+static_assert( is_constructible_v<span<const int>, const int(&)[2]> );
+
+static_assert( is_constructible_v<span<int>, array<int, 2>&> );
+static_assert( is_constructible_v<span<const int>, array<int, 2>&> );
+static_assert( is_constructible_v<span<const int>, array<const int, 2>&> );
+
+static_assert( is_constructible_v<span<int>, const array<int, 2>&> );
+static_assert( is_constructible_v<span<const int>, const array<int, 2>&> );
+static_assert( is_constructible_v<span<const int>, const array<const int, 2>&> );

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2019-09-30 11:51 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-30 11:51 [PATCH] Implement LWG 3255 for std::span constructors Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).