Merge pull request #854 from JordanMaples/dev/jomaples/LWG3255

Implement span std::array ctor changes from LWG3255
This commit is contained in:
Jordan Maples [MSFT] 2020-04-09 23:42:04 -07:00 коммит произвёл GitHub
Родитель b0b933b842 efbce17ca4
Коммит f7aae78ff6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 64 добавлений и 28 удалений

Просмотреть файл

@ -21,9 +21,9 @@
#include <gsl/gsl_byte> // for byte
#include <gsl/gsl_util> // for narrow_cast, narrow
#include <array> // for array
#include <cstddef> // for ptrdiff_t, size_t, nullptr_t
#include <iterator> // for reverse_iterator, distance, random_access_...
#include <array> // for array
#include <cstddef> // for ptrdiff_t, size_t, nullptr_t
#include <iterator> // for reverse_iterator, distance, random_access_...
#include <type_traits> // for enable_if_t, declval, is_convertible, inte...
#if defined(_MSC_VER) && !defined(__clang__)
@ -441,18 +441,21 @@ public:
: storage_(KnownNotNull{arr + 0}, details::extent_type<N>())
{}
template <std::size_t N,
std::enable_if_t<details::is_allowed_extent_conversion<N, Extent>::value, int> = 0>
constexpr span(std::array<element_type, N>& arr) noexcept
template <
class T, std::size_t N,
std::enable_if_t<(details::is_allowed_extent_conversion<N, Extent>::value &&
details::is_allowed_element_type_conversion<T, element_type>::value),
int> = 0>
constexpr span(std::array<T, N>& arr) noexcept
: storage_(KnownNotNull{arr.data()}, details::extent_type<N>())
{}
template <std::size_t N,
std::enable_if_t<(details::is_allowed_extent_conversion<N, Extent>::value &&
details::is_allowed_element_type_conversion<const value_type,
element_type>::value),
int> = 0>
constexpr span(const std::array<value_type, N>& arr) noexcept
template <class T, std::size_t N,
std::enable_if_t<
(details::is_allowed_extent_conversion<N, Extent>::value &&
details::is_allowed_element_type_conversion<const T, element_type>::value),
int> = 0>
constexpr span(const std::array<T, N>& arr) noexcept
: storage_(KnownNotNull{arr.data()}, details::extent_type<N>())
{}
@ -462,7 +465,9 @@ public:
class = std::enable_if_t<
!details::is_span<Container>::value && !details::is_std_array<Container>::value &&
std::is_pointer<decltype(std::declval<Container&>().data())>::value &&
std::is_convertible<std::remove_pointer_t<decltype(std::declval<Container&>().data())>(*)[], element_type(*)[]>::value>>
std::is_convertible<
std::remove_pointer_t<decltype(std::declval<Container&>().data())> (*)[],
element_type (*)[]>::value>>
constexpr span(Container& cont) noexcept : span(cont.data(), cont.size())
{}
@ -471,7 +476,9 @@ public:
std::is_const<element_type>::value && !details::is_span<Container>::value &&
!details::is_std_array<Container>::value &&
std::is_pointer<decltype(std::declval<const Container&>().data())>::value &&
std::is_convertible<std::remove_pointer_t<decltype(std::declval<const Container&>().data())>(*)[], element_type(*)[]>::value>>
std::is_convertible<std::remove_pointer_t<
decltype(std::declval<const Container&>().data())> (*)[],
element_type (*)[]>::value>>
constexpr span(const Container& cont) noexcept : span(cont.data(), cont.size())
{}
@ -500,8 +507,8 @@ public:
template <std::size_t Count>
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
constexpr span<element_type, Count> last() const noexcept
// clang-format on
constexpr span<element_type, Count> last() const noexcept
{
Expects(Count <= size());
return {data() + (size() - Count), Count};
@ -510,9 +517,9 @@ public:
template <std::size_t Offset, std::size_t Count = dynamic_extent>
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
constexpr auto subspan() const noexcept ->
typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type
// clang-format on
constexpr auto subspan() const noexcept ->
typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type
{
Expects((size() >= Offset) && (Count == dynamic_extent || (Count <= size() - Offset)));
@ -673,7 +680,8 @@ private:
template <std::size_t CallerExtent>
constexpr span<element_type, dynamic_extent> make_subspan(size_type offset, size_type count,
subspan_selector<CallerExtent>) const noexcept
subspan_selector<CallerExtent>) const
noexcept
{
const span<element_type, dynamic_extent> tmp(*this);
return tmp.subspan(offset, count);

Просмотреть файл

@ -24,7 +24,7 @@
#include <iterator> // for reverse_iterator, operator-, operator==
#include <type_traits> // for integral_constant<>::value, is_default_co...
#include <utility>
#include <vector> // for vector
#include <vector> // for vector
using namespace std;
using namespace gsl;
@ -42,11 +42,40 @@ static_assert(std::is_convertible<Derived*, Base*>::value, "std::is_convertible<
static_assert(!std::is_convertible<Derived (*)[], Base (*)[]>::value,
"!std::is_convertible<Derived(*)[], Base(*)[]>");
// int*(*) [], int const* const(*)[] was identified as an issue in CWG330 and the resolution was
// provided with N4261.
template <class T = int>
void ArrayConvertibilityCheck()
{
#if __cplusplus >= 201703l
if constexpr (std::is_convertible<T*(*) [], T const* const(*)[]>::value)
{
std::array<T*, 3> stl_nullptr{{nullptr, nullptr, nullptr}};
gsl::span<const T* const> sp_const_nullptr_1{stl_nullptr};
EXPECT_TRUE(sp_const_nullptr_1.data() == stl_nullptr.data());
EXPECT_TRUE(sp_const_nullptr_1.size() == 3);
span<const T* const> sp_const_nullptr_2{std::as_const(stl_nullptr)};
EXPECT_TRUE(sp_const_nullptr_2.data() == stl_nullptr.data());
EXPECT_TRUE(sp_const_nullptr_2.size() == 3);
static_assert(std::is_same<decltype(span{stl_nullptr}), span<T*, 3>>::value,
"std::is_same< decltype(span{stl_nullptr}), span<T*, 3>>::value");
static_assert(
std::is_same<decltype(span{std::as_const(stl_nullptr)}), span<T* const, 3>>::value,
"std::is_same< decltype(span{std::as_const(stl_nullptr)}), span<T* const, "
"3>>::value");
}
#endif
}
TEST(span_compatibility_tests, assertion_tests)
{
int arr[3]{10, 20, 30};
std::array<int, 3> stl{{100, 200, 300}};
ArrayConvertibilityCheck();
{
gsl::span<int> sp_dyn;
EXPECT_TRUE(sp_dyn.data() == nullptr);
@ -1052,21 +1081,20 @@ static_assert(std::is_convertible<std::array<int, 3>&, gsl::span<const int>>::va
static_assert(std::is_convertible<const std::array<int, 3>&, gsl::span<const int>>::value,
"std::is_convertible<const std::array<int, 3>&, gsl::span<const int>>");
#if __cplusplus >= 201703l
template <typename U, typename = void>
static constexpr bool AsWritableBytesCompilesFor = false;
template <typename U>
static constexpr bool AsWritableBytesCompilesFor<U, void_t<decltype(as_writable_bytes(declval<U>()))>> =
true;
static constexpr bool
AsWritableBytesCompilesFor<U, void_t<decltype(as_writable_bytes(declval<U>()))>> = true;
static_assert(AsWritableBytesCompilesFor<gsl::span<int>>,
"AsWritableBytesCompilesFor<gsl::span<int>>");
"AsWritableBytesCompilesFor<gsl::span<int>>");
static_assert(AsWritableBytesCompilesFor<gsl::span<int, 9>>,
"AsWritableBytesCompilesFor<gsl::span<int, 9>>");
"AsWritableBytesCompilesFor<gsl::span<int, 9>>");
static_assert(!AsWritableBytesCompilesFor<gsl::span<const int>>,
"!AsWritableBytesCompilesFor<gsl::span<const int>>");
"!AsWritableBytesCompilesFor<gsl::span<const int>>");
static_assert(!AsWritableBytesCompilesFor<gsl::span<const int, 9>>,
"!AsWritableBytesCompilesFor<gsl::span<const int, 9>>");
"!AsWritableBytesCompilesFor<gsl::span<const int, 9>>");
#endif // __cplusplus >= 201703l