mirror of
https://github.com/microsoft/GSL.git
synced 2024-11-03 17:56:43 -05:00
initial impl of P1976R2
This commit is contained in:
parent
1999b48a51
commit
2085c7acde
@ -420,18 +420,28 @@ public:
|
|||||||
constexpr span() noexcept : storage_(nullptr, details::extent_type<0>())
|
constexpr span() noexcept : storage_(nullptr, details::extent_type<0>())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
template<std::size_t extent = Extent, std::enable_if_t<extent != gsl::dynamic_extent, int> = 0>
|
||||||
constexpr span(pointer ptr, size_type count) noexcept : storage_(ptr, count)
|
constexpr span(pointer ptr, size_type count) noexcept : storage_(ptr, count)
|
||||||
{
|
{
|
||||||
if (Extent != dynamic_extent) Expects(count == Extent);
|
Expects(count == Extent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<std::size_t extent = Extent, std::enable_if_t<extent == gsl::dynamic_extent, int> = 0>
|
||||||
|
constexpr explicit span(pointer ptr, size_type count) noexcept : storage_(ptr, count)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<std::size_t extent = Extent, std::enable_if_t<extent != gsl::dynamic_extent, int> = 0>
|
||||||
constexpr span(pointer firstElem, pointer lastElem) noexcept
|
constexpr 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 extent = Extent, std::enable_if_t<extent == 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
|
||||||
@ -482,14 +492,25 @@ public:
|
|||||||
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 && OtherExtent == dynamic_extent) &&
|
||||||
details::is_allowed_element_type_conversion<OtherElementType, element_type>::value>>
|
(Extent == dynamic_extent || OtherExtent == dynamic_extent || Extent == OtherExtent) &&
|
||||||
|
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) &&
|
||||||
|
(Extent == dynamic_extent || OtherExtent == dynamic_extent || Extent == OtherExtent) &&
|
||||||
|
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;
|
||||||
|
|
||||||
@ -519,14 +540,14 @@ 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
|
||||||
{
|
{
|
||||||
Expects(count <= size());
|
Expects(count <= size());
|
||||||
return {data(), count};
|
return span<element_type>(data(), count);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr span<element_type, dynamic_extent> last(size_type count) const noexcept
|
constexpr span<element_type, dynamic_extent> last(size_type count) const noexcept
|
||||||
@ -731,7 +752,8 @@ as_bytes(span<ElementType, Extent> s) noexcept
|
|||||||
// 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 span<const byte, details::calculate_byte_size<ElementType, Extent>::value>(
|
||||||
|
reinterpret_cast<const byte*>(s.data()), s.size_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ElementType, std::size_t Extent,
|
template <class ElementType, std::size_t Extent,
|
||||||
@ -742,7 +764,8 @@ as_writable_bytes(span<ElementType, Extent> s) noexcept
|
|||||||
// 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 span<byte, details::calculate_byte_size<ElementType, Extent>::value>(
|
||||||
|
reinterpret_cast<byte*>(s.data()), s.size_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace gsl
|
} // namespace gsl
|
||||||
|
@ -121,7 +121,7 @@ span<T, dynamic_extent> ensure_sentinel(T* seq,
|
|||||||
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // TODO: suppress does not work
|
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // TODO: suppress does not work
|
||||||
while (static_cast<std::size_t>(cur - seq) < max && *cur != Sentinel) ++cur;
|
while (static_cast<std::size_t>(cur - seq) < max && *cur != Sentinel) ++cur;
|
||||||
Ensures(*cur == Sentinel);
|
Ensures(*cur == Sentinel);
|
||||||
return {seq, static_cast<std::size_t>(cur - seq)};
|
return span<T>(seq, static_cast<std::size_t>(cur - seq));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -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>>");
|
||||||
|
@ -320,7 +320,7 @@ TEST(span_ext_test, make_span_from_array_constructor)
|
|||||||
{
|
{
|
||||||
int arr[] = {1, 2, 3};
|
int arr[] = {1, 2, 3};
|
||||||
|
|
||||||
span<int> s1 = {&arr[0], 2}; // shorter
|
span<int> s1 = span<int>(&arr[0], 2); // shorter
|
||||||
span<int> s2 = arr; // longer
|
span<int> s2 = arr; // longer
|
||||||
|
|
||||||
EXPECT_TRUE(s1 != s2);
|
EXPECT_TRUE(s1 != s2);
|
||||||
|
@ -157,7 +157,7 @@ TEST(span_test, from_pointer_length_constructor)
|
|||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
span<int> s = {&arr[0], narrow_cast<std::size_t>(i)};
|
span<int> s = span<int>(&arr[0], narrow_cast<std::size_t>(i));
|
||||||
EXPECT_TRUE(s.size() == narrow_cast<std::size_t>(i));
|
EXPECT_TRUE(s.size() == narrow_cast<std::size_t>(i));
|
||||||
EXPECT_TRUE(s.data() == &arr[0]);
|
EXPECT_TRUE(s.data() == &arr[0]);
|
||||||
EXPECT_TRUE(s.empty() == (i == 0));
|
EXPECT_TRUE(s.empty() == (i == 0));
|
||||||
@ -165,7 +165,7 @@ TEST(span_test, from_pointer_length_constructor)
|
|||||||
EXPECT_TRUE(arr[j] == s[narrow_cast<std::size_t>(j)]);
|
EXPECT_TRUE(arr[j] == s[narrow_cast<std::size_t>(j)]);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
span<int> s = {&arr[i], 4 - narrow_cast<std::size_t>(i)};
|
span<int> s = span<int>(&arr[i], 4 - narrow_cast<std::size_t>(i));
|
||||||
EXPECT_TRUE(s.size() == 4 - narrow_cast<std::size_t>(i));
|
EXPECT_TRUE(s.size() == 4 - narrow_cast<std::size_t>(i));
|
||||||
EXPECT_TRUE(s.data() == &arr[i]);
|
EXPECT_TRUE(s.data() == &arr[i]);
|
||||||
EXPECT_TRUE(s.empty() == ((4 - i) == 0));
|
EXPECT_TRUE(s.empty() == ((4 - i) == 0));
|
||||||
@ -678,7 +678,7 @@ TEST(span_test, from_array_constructor)
|
|||||||
s2 = s1;
|
s2 = s1;
|
||||||
EXPECT_TRUE(s2.empty());
|
EXPECT_TRUE(s2.empty());
|
||||||
|
|
||||||
auto get_temp_span = [&]() -> span<int> { return {&arr[1], 2}; };
|
auto get_temp_span = [&]() -> span<int> { return span<int>(&arr[1], 2); };
|
||||||
auto use_span = [&](span<const int> s) {
|
auto use_span = [&](span<const int> s) {
|
||||||
EXPECT_TRUE(s.size() == 2);
|
EXPECT_TRUE(s.size() == 2);
|
||||||
EXPECT_TRUE(s.data() == &arr[1]);
|
EXPECT_TRUE(s.data() == &arr[1]);
|
||||||
|
@ -128,6 +128,7 @@ cu16zstring_span<> CreateTempNameU16(u16string_span<> span)
|
|||||||
span[last] = u'\0';
|
span[last] = u'\0';
|
||||||
|
|
||||||
auto ret = span.subspan(0, 4);
|
auto ret = span.subspan(0, 4);
|
||||||
|
// return cu16zstring_span<>(ret);
|
||||||
return {ret};
|
return {ret};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -960,7 +961,7 @@ TEST(string_span_tests, zstring)
|
|||||||
char buf[1];
|
char buf[1];
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
|
|
||||||
zstring_span<> zspan({buf, 1});
|
zstring_span<> zspan(span<char>(buf, 1));
|
||||||
|
|
||||||
EXPECT_TRUE(generic::strlen(zspan.assume_z()) == 0);
|
EXPECT_TRUE(generic::strlen(zspan.assume_z()) == 0);
|
||||||
EXPECT_TRUE(zspan.as_string_span().size() == 0);
|
EXPECT_TRUE(zspan.as_string_span().size() == 0);
|
||||||
@ -972,7 +973,7 @@ TEST(string_span_tests, zstring)
|
|||||||
char buf[1];
|
char buf[1];
|
||||||
buf[0] = 'a';
|
buf[0] = 'a';
|
||||||
|
|
||||||
auto workaround_macro = [&]() { const zstring_span<> zspan({buf, 1}); };
|
auto workaround_macro = [&]() { const zstring_span<> zspan(span<char>(buf, 1)); };
|
||||||
EXPECT_DEATH(workaround_macro(), deathstring);
|
EXPECT_DEATH(workaround_macro(), deathstring);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1001,7 +1002,7 @@ TEST(string_span_tests, wzstring)
|
|||||||
wchar_t buf[1];
|
wchar_t buf[1];
|
||||||
buf[0] = L'\0';
|
buf[0] = L'\0';
|
||||||
|
|
||||||
wzstring_span<> zspan({buf, 1});
|
wzstring_span<> zspan(span<wchar_t>(buf, 1));
|
||||||
|
|
||||||
EXPECT_TRUE(generic::strnlen(zspan.assume_z(), 1) == 0);
|
EXPECT_TRUE(generic::strnlen(zspan.assume_z(), 1) == 0);
|
||||||
EXPECT_TRUE(zspan.as_string_span().size() == 0);
|
EXPECT_TRUE(zspan.as_string_span().size() == 0);
|
||||||
@ -1013,7 +1014,7 @@ TEST(string_span_tests, wzstring)
|
|||||||
wchar_t buf[1];
|
wchar_t buf[1];
|
||||||
buf[0] = L'a';
|
buf[0] = L'a';
|
||||||
|
|
||||||
const auto workaround_macro = [&]() { const wzstring_span<> zspan({buf, 1}); };
|
const auto workaround_macro = [&]() { const wzstring_span<> zspan(span<wchar_t>(buf, 1)); };
|
||||||
EXPECT_DEATH(workaround_macro(), deathstring);
|
EXPECT_DEATH(workaround_macro(), deathstring);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1042,7 +1043,7 @@ TEST(string_span_tests, u16zstring)
|
|||||||
char16_t buf[1];
|
char16_t buf[1];
|
||||||
buf[0] = L'\0';
|
buf[0] = L'\0';
|
||||||
|
|
||||||
u16zstring_span<> zspan({buf, 1});
|
u16zstring_span<> zspan(span<char16_t>(buf, 1));
|
||||||
|
|
||||||
EXPECT_TRUE(generic::strnlen(zspan.assume_z(), 1) == 0);
|
EXPECT_TRUE(generic::strnlen(zspan.assume_z(), 1) == 0);
|
||||||
EXPECT_TRUE(zspan.as_string_span().size() == 0);
|
EXPECT_TRUE(zspan.as_string_span().size() == 0);
|
||||||
@ -1054,7 +1055,7 @@ TEST(string_span_tests, u16zstring)
|
|||||||
char16_t buf[1];
|
char16_t buf[1];
|
||||||
buf[0] = u'a';
|
buf[0] = u'a';
|
||||||
|
|
||||||
const auto workaround_macro = [&]() { const u16zstring_span<> zspan({buf, 1}); };
|
const auto workaround_macro = [&]() { const u16zstring_span<> zspan(span<char16_t>(buf, 1)); };
|
||||||
EXPECT_DEATH(workaround_macro(), deathstring);
|
EXPECT_DEATH(workaround_macro(), deathstring);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1083,7 +1084,7 @@ TEST(string_span_tests, u32zstring)
|
|||||||
char32_t buf[1];
|
char32_t buf[1];
|
||||||
buf[0] = L'\0';
|
buf[0] = L'\0';
|
||||||
|
|
||||||
u32zstring_span<> zspan({buf, 1});
|
u32zstring_span<> zspan(span<char32_t>(buf, 1));
|
||||||
|
|
||||||
EXPECT_TRUE(generic::strnlen(zspan.assume_z(), 1) == 0);
|
EXPECT_TRUE(generic::strnlen(zspan.assume_z(), 1) == 0);
|
||||||
EXPECT_TRUE(zspan.as_string_span().size() == 0);
|
EXPECT_TRUE(zspan.as_string_span().size() == 0);
|
||||||
@ -1095,7 +1096,7 @@ TEST(string_span_tests, u32zstring)
|
|||||||
char32_t buf[1];
|
char32_t buf[1];
|
||||||
buf[0] = u'a';
|
buf[0] = u'a';
|
||||||
|
|
||||||
const auto workaround_macro = [&]() { const u32zstring_span<> zspan({buf, 1}); };
|
const auto workaround_macro = [&]() { const u32zstring_span<> zspan(span<char32_t>(buf, 1)); };
|
||||||
EXPECT_DEATH(workaround_macro(), deathstring);
|
EXPECT_DEATH(workaround_macro(), deathstring);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user