mirror of
https://github.com/microsoft/GSL.git
synced 2024-11-03 17:56:43 -05:00
Merge pull request #887 from JordanMaples/dev/jomaples/p1976r2
gsl::span P1976R2 implemenation
This commit is contained in:
commit
8cd19412b4
116
include/gsl/span
116
include/gsl/span
@ -343,15 +343,9 @@ namespace details
|
|||||||
|
|
||||||
constexpr extent_type() noexcept = default;
|
constexpr extent_type() noexcept = default;
|
||||||
|
|
||||||
template <size_type Other>
|
constexpr explicit extent_type(extent_type<dynamic_extent>);
|
||||||
constexpr extent_type(extent_type<Other> ext)
|
|
||||||
{
|
|
||||||
static_assert(Other == Ext,
|
|
||||||
"Mismatch between fixed-size extent and size of initializing data.");
|
|
||||||
Expects(ext.size() == Ext);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr extent_type(size_type size) { Expects(size == Ext); }
|
constexpr explicit extent_type(size_type size) { Expects(size == Ext); }
|
||||||
|
|
||||||
constexpr size_type size() const noexcept { return Ext; }
|
constexpr size_type size() const noexcept { return Ext; }
|
||||||
};
|
};
|
||||||
@ -363,10 +357,10 @@ namespace details
|
|||||||
using size_type = std::size_t;
|
using size_type = std::size_t;
|
||||||
|
|
||||||
template <size_type Other>
|
template <size_type Other>
|
||||||
explicit constexpr extent_type(extent_type<Other> ext) : size_(ext.size())
|
constexpr explicit extent_type(extent_type<Other> ext) : size_(ext.size())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
explicit constexpr extent_type(size_type size) : size_(size)
|
constexpr explicit extent_type(size_type size) : size_(size)
|
||||||
{
|
{
|
||||||
Expects(size != dynamic_extent);
|
Expects(size != dynamic_extent);
|
||||||
}
|
}
|
||||||
@ -377,6 +371,12 @@ namespace details
|
|||||||
size_type size_;
|
size_type size_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <std::size_t Ext>
|
||||||
|
constexpr extent_type<Ext>::extent_type(extent_type<dynamic_extent> ext)
|
||||||
|
{
|
||||||
|
Expects(ext.size() == Ext);
|
||||||
|
}
|
||||||
|
|
||||||
template <class ElementType, std::size_t Extent, std::size_t Offset, std::size_t Count>
|
template <class ElementType, std::size_t Extent, std::size_t Offset, std::size_t Count>
|
||||||
struct calculate_subspan_type
|
struct calculate_subspan_type
|
||||||
{
|
{
|
||||||
@ -420,18 +420,28 @@ public:
|
|||||||
constexpr span() noexcept : storage_(nullptr, details::extent_type<0>())
|
constexpr span() noexcept : storage_(nullptr, details::extent_type<0>())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
constexpr span(pointer ptr, size_type count) noexcept : storage_(ptr, count)
|
template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent != gsl::dynamic_extent, int> = 0>
|
||||||
|
constexpr explicit span(pointer ptr, size_type count) noexcept : storage_(ptr, count)
|
||||||
{
|
{
|
||||||
if (Extent != dynamic_extent) Expects(count == Extent);
|
Expects(count == Extent);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr span(pointer firstElem, pointer lastElem) noexcept
|
template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent == gsl::dynamic_extent, int> = 0>
|
||||||
|
constexpr span(pointer ptr, size_type count) noexcept : storage_(ptr, count)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent != gsl::dynamic_extent, int> = 0>
|
||||||
|
constexpr explicit span(pointer firstElem, pointer lastElem) noexcept
|
||||||
: storage_(firstElem, static_cast<std::size_t>(lastElem - firstElem))
|
: storage_(firstElem, static_cast<std::size_t>(lastElem - firstElem))
|
||||||
{
|
{
|
||||||
if (Extent != dynamic_extent)
|
Expects(lastElem - firstElem == static_cast<difference_type>(Extent));
|
||||||
{ Expects(lastElem - firstElem == static_cast<difference_type>(Extent)); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent == gsl::dynamic_extent, int> = 0>
|
||||||
|
constexpr span(pointer firstElem, pointer lastElem) noexcept
|
||||||
|
: storage_(firstElem, static_cast<std::size_t>(lastElem - firstElem))
|
||||||
|
{}
|
||||||
|
|
||||||
template <std::size_t N,
|
template <std::size_t N,
|
||||||
std::enable_if_t<details::is_allowed_extent_conversion<N, Extent>::value, int> = 0>
|
std::enable_if_t<details::is_allowed_extent_conversion<N, Extent>::value, int> = 0>
|
||||||
constexpr span(element_type (&arr)[N]) noexcept
|
constexpr span(element_type (&arr)[N]) noexcept
|
||||||
@ -456,40 +466,74 @@ public:
|
|||||||
: storage_(KnownNotNull{arr.data()}, details::extent_type<N>())
|
: storage_(KnownNotNull{arr.data()}, details::extent_type<N>())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// NB: the SFINAE here uses .data() as an incomplete/imperfect proxy for the requirement
|
// NB: the SFINAE on these constructors uses .data() as an incomplete/imperfect proxy for the
|
||||||
// on Container to be a contiguous sequence container.
|
// requirement on Container to be a contiguous sequence container.
|
||||||
template <class Container,
|
template <std::size_t MyExtent = Extent, class Container,
|
||||||
class = std::enable_if_t<
|
std::enable_if_t<
|
||||||
|
MyExtent != dynamic_extent &&
|
||||||
!details::is_span<Container>::value && !details::is_std_array<Container>::value &&
|
!details::is_span<Container>::value && !details::is_std_array<Container>::value &&
|
||||||
std::is_pointer<decltype(std::declval<Container&>().data())>::value &&
|
std::is_pointer<decltype(std::declval<Container&>().data())>::value &&
|
||||||
std::is_convertible<
|
std::is_convertible<
|
||||||
std::remove_pointer_t<decltype(std::declval<Container&>().data())> (*)[],
|
std::remove_pointer_t<decltype(std::declval<Container&>().data())> (*)[],
|
||||||
element_type (*)[]>::value>>
|
element_type (*)[]>::value, int> = 0>
|
||||||
|
constexpr explicit span(Container& cont) noexcept : span(cont.data(), cont.size())
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <std::size_t MyExtent = Extent, class Container,
|
||||||
|
std::enable_if_t<
|
||||||
|
MyExtent == dynamic_extent &&
|
||||||
|
!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, int> = 0>
|
||||||
constexpr span(Container& cont) noexcept : span(cont.data(), cont.size())
|
constexpr span(Container& cont) noexcept : span(cont.data(), cont.size())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <class Container,
|
template <std::size_t MyExtent = Extent, class Container,
|
||||||
class = std::enable_if_t<
|
std::enable_if_t<
|
||||||
|
MyExtent != dynamic_extent &&
|
||||||
std::is_const<element_type>::value && !details::is_span<Container>::value &&
|
std::is_const<element_type>::value && !details::is_span<Container>::value &&
|
||||||
!details::is_std_array<Container>::value &&
|
!details::is_std_array<Container>::value &&
|
||||||
std::is_pointer<decltype(std::declval<const Container&>().data())>::value &&
|
std::is_pointer<decltype(std::declval<const Container&>().data())>::value &&
|
||||||
std::is_convertible<std::remove_pointer_t<
|
std::is_convertible<std::remove_pointer_t<
|
||||||
decltype(std::declval<const Container&>().data())> (*)[],
|
decltype(std::declval<const Container&>().data())> (*)[],
|
||||||
element_type (*)[]>::value>>
|
element_type (*)[]>::value, int> = 0>
|
||||||
|
constexpr explicit span(const Container& cont) noexcept : span(cont.data(), cont.size())
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <std::size_t MyExtent = Extent, class Container,
|
||||||
|
std::enable_if_t<
|
||||||
|
MyExtent == dynamic_extent &&
|
||||||
|
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, int> = 0>
|
||||||
constexpr span(const Container& cont) noexcept : span(cont.data(), cont.size())
|
constexpr span(const Container& cont) noexcept : span(cont.data(), cont.size())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
constexpr span(const span& other) noexcept = default;
|
constexpr span(const span& other) noexcept = default;
|
||||||
|
|
||||||
template <
|
template <
|
||||||
class OtherElementType, std::size_t OtherExtent,
|
class OtherElementType, std::size_t OtherExtent, std::size_t MyExtent = Extent,
|
||||||
class = std::enable_if_t<
|
std::enable_if_t<
|
||||||
details::is_allowed_extent_conversion<OtherExtent, Extent>::value &&
|
(MyExtent == dynamic_extent || MyExtent == OtherExtent) &&
|
||||||
details::is_allowed_element_type_conversion<OtherElementType, element_type>::value>>
|
details::is_allowed_element_type_conversion<OtherElementType, element_type>::value, int> = 0>
|
||||||
constexpr span(const span<OtherElementType, OtherExtent>& other) noexcept
|
constexpr span(const span<OtherElementType, OtherExtent>& other) noexcept
|
||||||
: storage_(other.data(), details::extent_type<OtherExtent>(other.size()))
|
: storage_(other.data(), details::extent_type<OtherExtent>(other.size()))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
template <
|
||||||
|
class OtherElementType, std::size_t OtherExtent, std::size_t MyExtent = Extent,
|
||||||
|
std::enable_if_t<
|
||||||
|
MyExtent != dynamic_extent && OtherExtent == dynamic_extent &&
|
||||||
|
details::is_allowed_element_type_conversion<OtherElementType, element_type>::value, int> = 0>
|
||||||
|
constexpr explicit span(const span<OtherElementType, OtherExtent>& other) noexcept
|
||||||
|
: storage_(other.data(), details::extent_type<OtherExtent>(other.size()))
|
||||||
|
{}
|
||||||
|
|
||||||
~span() noexcept = default;
|
~span() noexcept = default;
|
||||||
constexpr span& operator=(const span& other) noexcept = default;
|
constexpr span& operator=(const span& other) noexcept = default;
|
||||||
|
|
||||||
@ -498,7 +542,7 @@ public:
|
|||||||
constexpr span<element_type, Count> first() const noexcept
|
constexpr span<element_type, Count> first() const noexcept
|
||||||
{
|
{
|
||||||
Expects(Count <= size());
|
Expects(Count <= size());
|
||||||
return {data(), Count};
|
return span<element_type, Count>{data(), Count};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t Count>
|
template <std::size_t Count>
|
||||||
@ -508,7 +552,7 @@ public:
|
|||||||
constexpr span<element_type, Count> last() const noexcept
|
constexpr span<element_type, Count> last() const noexcept
|
||||||
{
|
{
|
||||||
Expects(Count <= size());
|
Expects(Count <= size());
|
||||||
return {data() + (size() - Count), Count};
|
return span<element_type, Count>{data() + (size() - Count), Count};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t Offset, std::size_t Count = dynamic_extent>
|
template <std::size_t Offset, std::size_t Count = dynamic_extent>
|
||||||
@ -519,8 +563,8 @@ public:
|
|||||||
typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type
|
typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type
|
||||||
{
|
{
|
||||||
Expects((size() >= Offset) && (Count == dynamic_extent || (Count <= size() - Offset)));
|
Expects((size() >= Offset) && (Count == dynamic_extent || (Count <= size() - Offset)));
|
||||||
|
using type = typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type;
|
||||||
return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count};
|
return type{data() + Offset, Count == dynamic_extent ? size() - Offset : Count};
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr span<element_type, dynamic_extent> first(size_type count) const noexcept
|
constexpr span<element_type, dynamic_extent> first(size_type count) const noexcept
|
||||||
@ -728,10 +772,12 @@ template <class ElementType, std::size_t Extent>
|
|||||||
span<const byte, details::calculate_byte_size<ElementType, Extent>::value>
|
span<const byte, details::calculate_byte_size<ElementType, Extent>::value>
|
||||||
as_bytes(span<ElementType, Extent> s) noexcept
|
as_bytes(span<ElementType, Extent> s) noexcept
|
||||||
{
|
{
|
||||||
|
using type = span<const byte, details::calculate_byte_size<ElementType, Extent>::value>;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
|
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
|
||||||
// clang-format on
|
// clang-format on
|
||||||
return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
|
return type{reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ElementType, std::size_t Extent,
|
template <class ElementType, std::size_t Extent,
|
||||||
@ -739,10 +785,12 @@ template <class ElementType, std::size_t Extent,
|
|||||||
span<byte, details::calculate_byte_size<ElementType, Extent>::value>
|
span<byte, details::calculate_byte_size<ElementType, Extent>::value>
|
||||||
as_writable_bytes(span<ElementType, Extent> s) noexcept
|
as_writable_bytes(span<ElementType, Extent> s) noexcept
|
||||||
{
|
{
|
||||||
|
using type = span<byte, details::calculate_byte_size<ElementType, Extent>::value>;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
|
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
|
||||||
// clang-format on
|
// clang-format on
|
||||||
return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
|
return type{reinterpret_cast<byte*>(s.data()), s.size_bytes()};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace gsl
|
} // namespace gsl
|
||||||
|
@ -308,7 +308,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
static impl_type remove_z(pointer const& sz, std::size_t max)
|
static impl_type remove_z(pointer const& sz, std::size_t max)
|
||||||
{
|
{
|
||||||
return {sz, details::string_length(sz, max)};
|
return impl_type(sz, details::string_length(sz, max));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t N>
|
template <std::size_t N>
|
||||||
|
@ -846,8 +846,6 @@ static_assert(!std::is_constructible<gsl::span<int, 3>, std::array<int, 500>&>::
|
|||||||
"!std::is_constructible<gsl::span<int, 3>, std::array<int, 500>&>");
|
"!std::is_constructible<gsl::span<int, 3>, std::array<int, 500>&>");
|
||||||
static_assert(!std::is_constructible<gsl::span<int, 3>, const std::array<int, 3>&>::value,
|
static_assert(!std::is_constructible<gsl::span<int, 3>, const std::array<int, 3>&>::value,
|
||||||
"!std::is_constructible<gsl::span<int, 3>, const std::array<int, 3>&>");
|
"!std::is_constructible<gsl::span<int, 3>, const std::array<int, 3>&>");
|
||||||
static_assert(!std::is_constructible<gsl::span<int, 3>, const gsl::span<int>&>::value,
|
|
||||||
"!std::is_constructible<gsl::span<int, 3>, const gsl::span<int>&>");
|
|
||||||
static_assert(!std::is_constructible<gsl::span<int, 3>, const gsl::span<int, 500>&>::value,
|
static_assert(!std::is_constructible<gsl::span<int, 3>, const gsl::span<int, 500>&>::value,
|
||||||
"!std::is_constructible<gsl::span<int, 3>, const gsl::span<int, 500>&>");
|
"!std::is_constructible<gsl::span<int, 3>, const gsl::span<int, 500>&>");
|
||||||
static_assert(!std::is_constructible<gsl::span<int, 3>, const gsl::span<const int>&>::value,
|
static_assert(!std::is_constructible<gsl::span<int, 3>, const gsl::span<const int>&>::value,
|
||||||
@ -866,12 +864,8 @@ static_assert(!std::is_constructible<gsl::span<const int>, std::array<double, 3>
|
|||||||
static_assert(!std::is_constructible<gsl::span<const int>, const gsl::span<double, 3>&>::value,
|
static_assert(!std::is_constructible<gsl::span<const int>, const gsl::span<double, 3>&>::value,
|
||||||
"!std::is_constructible<gsl::span<const int>, const gsl::span<double, 3>&>");
|
"!std::is_constructible<gsl::span<const int>, const gsl::span<double, 3>&>");
|
||||||
|
|
||||||
static_assert(!std::is_constructible<gsl::span<const int, 3>, const gsl::span<int>&>::value,
|
|
||||||
"!std::is_constructible<gsl::span<const int, 3>, const gsl::span<int>&>");
|
|
||||||
static_assert(!std::is_constructible<gsl::span<const int, 3>, const gsl::span<int, 500>&>::value,
|
static_assert(!std::is_constructible<gsl::span<const int, 3>, const gsl::span<int, 500>&>::value,
|
||||||
"!std::is_constructible<gsl::span<const int, 3>, const gsl::span<int, 500>&>");
|
"!std::is_constructible<gsl::span<const int, 3>, const gsl::span<int, 500>&>");
|
||||||
static_assert(!std::is_constructible<gsl::span<const int, 3>, const gsl::span<const int>&>::value,
|
|
||||||
"!std::is_constructible<gsl::span<const int, 3>, const gsl::span<const int>&>");
|
|
||||||
static_assert(
|
static_assert(
|
||||||
!std::is_constructible<gsl::span<const int, 3>, const gsl::span<const int, 500>&>::value,
|
!std::is_constructible<gsl::span<const int, 3>, const gsl::span<const int, 500>&>::value,
|
||||||
"!std::is_constructible<gsl::span<const int, 3>, const gsl::span<const int, 500>&>");
|
"!std::is_constructible<gsl::span<const int, 3>, const gsl::span<const int, 500>&>");
|
||||||
@ -925,6 +919,14 @@ static_assert(!std::is_constructible<gsl::span<const Derived>, std::array<Base,
|
|||||||
static_assert(!std::is_constructible<gsl::span<const Derived>, const std::array<Base, 3>&>::value,
|
static_assert(!std::is_constructible<gsl::span<const Derived>, const std::array<Base, 3>&>::value,
|
||||||
"!std::is_constructible<gsl::span<const Derived>, const std::array<Base, 3>&>");
|
"!std::is_constructible<gsl::span<const Derived>, const std::array<Base, 3>&>");
|
||||||
|
|
||||||
|
// Explicit construction enabled in P1976R2
|
||||||
|
static_assert(std::is_constructible<gsl::span<int, 3>, const gsl::span<int>&>::value,
|
||||||
|
"std::is_constructible<gsl::span<int, 3>, const gsl::span<int>&>");
|
||||||
|
static_assert(std::is_constructible<gsl::span<const int, 3>, const gsl::span<int>&>::value,
|
||||||
|
"std::is_constructible<gsl::span<const int, 3>, const gsl::span<int>&>");
|
||||||
|
static_assert(std::is_constructible<gsl::span<const int, 3>, const gsl::span<const int>&>::value,
|
||||||
|
"std::is_constructible<gsl::span<const int, 3>, const gsl::span<const int>&>");
|
||||||
|
|
||||||
// no throw copy constructor
|
// no throw copy constructor
|
||||||
static_assert(std::is_nothrow_copy_constructible<gsl::span<int>>::value,
|
static_assert(std::is_nothrow_copy_constructible<gsl::span<int>>::value,
|
||||||
"std::is_nothrow_copy_constructible<gsl::span<int>>");
|
"std::is_nothrow_copy_constructible<gsl::span<int>>");
|
||||||
|
@ -1144,7 +1144,7 @@ TEST(span_test, from_array_constructor)
|
|||||||
|
|
||||||
// you can convert statically
|
// you can convert statically
|
||||||
{
|
{
|
||||||
const span<int, 2> s2 = {&arr[0], 2};
|
const span<int, 2> s2{&arr[0], 2};
|
||||||
static_cast<void>(s2);
|
static_cast<void>(s2);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -1180,7 +1180,7 @@ TEST(span_test, from_array_constructor)
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
auto f = [&]() {
|
auto f = [&]() {
|
||||||
const span<int, 4> _s4 = {arr2, 2};
|
const span<int, 4> _s4{arr2, 2};
|
||||||
static_cast<void>(_s4);
|
static_cast<void>(_s4);
|
||||||
};
|
};
|
||||||
EXPECT_DEATH(f(), deathstring);
|
EXPECT_DEATH(f(), deathstring);
|
||||||
|
Loading…
Reference in New Issue
Block a user