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. From-SVN: r276298
This commit is contained in:
parent
6438d29fb1
commit
582c57a17e
@ -1,5 +1,12 @@
|
||||
2019-09-30 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* 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.
|
||||
|
||||
PR libstdc++/77936
|
||||
* include/parallel/checkers.h (__is_sorted): Remove unused variable.
|
||||
|
||||
|
@ -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
|
||||
|
69
libstdc++-v3/testsuite/23_containers/span/lwg3255.cc
Normal file
69
libstdc++-v3/testsuite/23_containers/span/lwg3255.cc
Normal file
@ -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>&> );
|
Loading…
Reference in New Issue
Block a user