Add span::subspan
This commit is contained in:
14
MODULE.bazel.lock
generated
14
MODULE.bazel.lock
generated
@ -64,20 +64,20 @@
|
|||||||
"@@apple_support~//crosstool:setup.bzl%apple_cc_configure_extension": {
|
"@@apple_support~//crosstool:setup.bzl%apple_cc_configure_extension": {
|
||||||
"general": {
|
"general": {
|
||||||
"bzlTransitiveDigest": "PjIds3feoYE8SGbbIq2SFTZy3zmxeO2tQevJZNDo7iY=",
|
"bzlTransitiveDigest": "PjIds3feoYE8SGbbIq2SFTZy3zmxeO2tQevJZNDo7iY=",
|
||||||
"usagesDigest": "aLmqbvowmHkkBPve05yyDNGN7oh7QE9kBADr3QIZTZs=",
|
"usagesDigest": "+hz7IHWN6A1oVJJWNDB6yZRG+RYhF76wAYItpAeIUIg=",
|
||||||
"recordedFileInputs": {},
|
"recordedFileInputs": {},
|
||||||
"recordedDirentsInputs": {},
|
"recordedDirentsInputs": {},
|
||||||
"envVariables": {},
|
"envVariables": {},
|
||||||
"generatedRepoSpecs": {
|
"generatedRepoSpecs": {
|
||||||
"local_config_apple_cc": {
|
|
||||||
"bzlFile": "@@apple_support~//crosstool:setup.bzl",
|
|
||||||
"ruleClassName": "_apple_cc_autoconf",
|
|
||||||
"attributes": {}
|
|
||||||
},
|
|
||||||
"local_config_apple_cc_toolchains": {
|
"local_config_apple_cc_toolchains": {
|
||||||
"bzlFile": "@@apple_support~//crosstool:setup.bzl",
|
"bzlFile": "@@apple_support~//crosstool:setup.bzl",
|
||||||
"ruleClassName": "_apple_cc_autoconf_toolchains",
|
"ruleClassName": "_apple_cc_autoconf_toolchains",
|
||||||
"attributes": {}
|
"attributes": {}
|
||||||
|
},
|
||||||
|
"local_config_apple_cc": {
|
||||||
|
"bzlFile": "@@apple_support~//crosstool:setup.bzl",
|
||||||
|
"ruleClassName": "_apple_cc_autoconf",
|
||||||
|
"attributes": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"recordedRepoMappingEntries": [
|
"recordedRepoMappingEntries": [
|
||||||
@ -92,7 +92,7 @@
|
|||||||
"@@platforms//host:extension.bzl%host_platform": {
|
"@@platforms//host:extension.bzl%host_platform": {
|
||||||
"general": {
|
"general": {
|
||||||
"bzlTransitiveDigest": "xelQcPZH8+tmuOHVjL9vDxMnnQNMlwj0SlvgoqBkm4U=",
|
"bzlTransitiveDigest": "xelQcPZH8+tmuOHVjL9vDxMnnQNMlwj0SlvgoqBkm4U=",
|
||||||
"usagesDigest": "meSzxn3DUCcYEhq4HQwExWkWtU4EjriRBQLsZN+Q0SU=",
|
"usagesDigest": "pCYpDQmqMbmiiPI1p2Kd3VLm5T48rRAht5WdW0X2GlA=",
|
||||||
"recordedFileInputs": {},
|
"recordedFileInputs": {},
|
||||||
"recordedDirentsInputs": {},
|
"recordedDirentsInputs": {},
|
||||||
"envVariables": {},
|
"envVariables": {},
|
||||||
|
55
asl/span.hpp
55
asl/span.hpp
@ -13,7 +13,12 @@ static constexpr int64_t dynamic_size = -1;
|
|||||||
template<is_object T, int64_t kSize = dynamic_size>
|
template<is_object T, int64_t kSize = dynamic_size>
|
||||||
class span
|
class span
|
||||||
{
|
{
|
||||||
static constexpr bool kIsDynamic = kSize < 0;
|
static constexpr bool is_dynamic(int64_t size)
|
||||||
|
{
|
||||||
|
return size < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr bool kIsDynamic = is_dynamic(kSize);
|
||||||
|
|
||||||
using SizeType = select_t<kIsDynamic, int64_t, empty>;
|
using SizeType = select_t<kIsDynamic, int64_t, empty>;
|
||||||
|
|
||||||
@ -21,7 +26,7 @@ class span
|
|||||||
ASL_NO_UNIQUE_ADDRESS SizeType m_size{};
|
ASL_NO_UNIQUE_ADDRESS SizeType m_size{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr span() = default;
|
constexpr span() requires (kIsDynamic || kSize == 0) = default;
|
||||||
|
|
||||||
constexpr span(T* data, int64_t size)
|
constexpr span(T* data, int64_t size)
|
||||||
requires kIsDynamic
|
requires kIsDynamic
|
||||||
@ -55,7 +60,7 @@ public:
|
|||||||
requires (
|
requires (
|
||||||
(
|
(
|
||||||
kIsDynamic ||
|
kIsDynamic ||
|
||||||
span<U, kOtherSize>::kIsDynamic ||
|
is_dynamic(kOtherSize) ||
|
||||||
kOtherSize == kSize
|
kOtherSize == kSize
|
||||||
) && convertible_from<T(&)[], U(&)[]>
|
) && convertible_from<T(&)[], U(&)[]>
|
||||||
)
|
)
|
||||||
@ -92,11 +97,49 @@ public:
|
|||||||
return m_data[i]; // NOLINT(*-pointer-arithmetic)
|
return m_data[i]; // NOLINT(*-pointer-arithmetic)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Todo subspan, first, last
|
// @Todo first, last
|
||||||
// @Todo as_(mutable_)bytes
|
// @Todo as_(mutable_)bytes
|
||||||
|
|
||||||
template<is_object U, int64_t kOtherSize>
|
template<int64_t kOffset, int64_t kSubSize = dynamic_size>
|
||||||
friend class span;
|
constexpr auto subspan() const
|
||||||
|
requires (
|
||||||
|
kOffset >= 0 &&
|
||||||
|
(kIsDynamic || kOffset <= kSize) &&
|
||||||
|
(kIsDynamic || is_dynamic(kSubSize) || kSubSize <= kSize - kOffset)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ASL_ASSERT(kOffset <= size());
|
||||||
|
|
||||||
|
if constexpr (is_dynamic(kSubSize))
|
||||||
|
{
|
||||||
|
if constexpr (kIsDynamic)
|
||||||
|
{
|
||||||
|
return span<T>(data() + kOffset, size() - kOffset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return span<T, kSize - kOffset>(data() + kOffset, size() - kOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ASL_ASSERT(kSubSize <= size() - kOffset);
|
||||||
|
return span<T, kSubSize>(data() + kOffset, kSubSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr span<T> subspan(int64_t offset, int64_t sub_size = dynamic_size) const
|
||||||
|
{
|
||||||
|
ASL_ASSERT(offset <= size());
|
||||||
|
|
||||||
|
if (is_dynamic(sub_size))
|
||||||
|
{
|
||||||
|
return span<T>{ data() + offset, size() - offset };
|
||||||
|
}
|
||||||
|
|
||||||
|
ASL_ASSERT(sub_size <= size() - offset);
|
||||||
|
return span<T>{ data() + offset, sub_size };
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace asl
|
} // namespace asl
|
||||||
|
@ -38,6 +38,10 @@ ASL_TEST(from_array_dynamic)
|
|||||||
ASL_TEST_EXPECT(span[2] == 3);
|
ASL_TEST_EXPECT(span[2] == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static_assert(asl::default_constructible<asl::span<int>>);
|
||||||
|
static_assert(asl::default_constructible<asl::span<int, 0>>);
|
||||||
|
static_assert(!asl::default_constructible<asl::span<int, 8>>);
|
||||||
|
|
||||||
static_assert(asl::constructible_from<asl::span<int32_t>, int32_t(&)[8]>);
|
static_assert(asl::constructible_from<asl::span<int32_t>, int32_t(&)[8]>);
|
||||||
static_assert(!asl::constructible_from<asl::span<int32_t>, const int32_t(&)[8]>);
|
static_assert(!asl::constructible_from<asl::span<int32_t>, const int32_t(&)[8]>);
|
||||||
static_assert(asl::constructible_from<asl::span<const int32_t>, int32_t(&)[8]>);
|
static_assert(asl::constructible_from<asl::span<const int32_t>, int32_t(&)[8]>);
|
||||||
@ -89,3 +93,125 @@ ASL_TEST(conversion)
|
|||||||
ASL_TEST_EXPECT(span4[1] == 2);
|
ASL_TEST_EXPECT(span4[1] == 2);
|
||||||
ASL_TEST_EXPECT(span4[2] == 3);
|
ASL_TEST_EXPECT(span4[2] == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Span, int64_t kOffset, int64_t kSize = asl::dynamic_size>
|
||||||
|
[[maybe_unused]] static auto try_static_subspan(int)
|
||||||
|
-> decltype(asl::declval<Span>().template subspan<kOffset, kSize>());
|
||||||
|
|
||||||
|
template<typename, int64_t, int64_t>
|
||||||
|
[[maybe_unused]] static auto try_static_subspan(...) -> asl::empty;
|
||||||
|
|
||||||
|
template<typename Span, int64_t kOffset, int64_t kSize = asl::dynamic_size>
|
||||||
|
concept invalid_subspan = asl::same_as<decltype(try_static_subspan<Span, kOffset, kSize>(0)), asl::empty>;
|
||||||
|
|
||||||
|
static_assert(asl::same_as<asl::span<int, 4>,
|
||||||
|
decltype(asl::declval<asl::span<int, 4>>().subspan<0>())>);
|
||||||
|
|
||||||
|
static_assert(asl::same_as<asl::span<int, 3>,
|
||||||
|
decltype(asl::declval<asl::span<int, 4>>().subspan<1>())>);
|
||||||
|
|
||||||
|
static_assert(asl::same_as<asl::span<int, 2>,
|
||||||
|
decltype(asl::declval<asl::span<int, 4>>().subspan<2>())>);
|
||||||
|
|
||||||
|
static_assert(asl::same_as<asl::span<int, 1>,
|
||||||
|
decltype(asl::declval<asl::span<int, 4>>().subspan<3>())>);
|
||||||
|
|
||||||
|
static_assert(asl::same_as<asl::span<int, 0>,
|
||||||
|
decltype(asl::declval<asl::span<int, 4>>().subspan<4>())>);
|
||||||
|
|
||||||
|
static_assert(invalid_subspan<asl::span<int, 4>, 5>);
|
||||||
|
|
||||||
|
static_assert(asl::same_as<asl::span<int>,
|
||||||
|
decltype(asl::declval<asl::span<int>>().subspan<0>())>);
|
||||||
|
|
||||||
|
static_assert(asl::same_as<asl::span<int, 4>,
|
||||||
|
decltype(asl::declval<asl::span<int>>().subspan<0, 4>())>);
|
||||||
|
|
||||||
|
static_assert(asl::same_as<asl::span<int, 4>,
|
||||||
|
decltype(asl::declval<asl::span<int, 4>>().subspan<0, 4>())>);
|
||||||
|
|
||||||
|
static_assert(asl::same_as<asl::span<int, 2>,
|
||||||
|
decltype(asl::declval<asl::span<int, 4>>().subspan<1, 2>())>);
|
||||||
|
|
||||||
|
static_assert(asl::same_as<asl::span<int, 2>,
|
||||||
|
decltype(asl::declval<asl::span<int, 4>>().subspan<2, 2>())>);
|
||||||
|
|
||||||
|
static_assert(invalid_subspan<asl::span<int, 4>, 2, 3>);
|
||||||
|
|
||||||
|
ASL_TEST(subspan_static_from_static)
|
||||||
|
{
|
||||||
|
int array[] = {1, 2, 3, 4};
|
||||||
|
asl::span<int, 4> span{array};
|
||||||
|
|
||||||
|
auto s1 = span.subspan<0>();
|
||||||
|
ASL_TEST_EXPECT(s1.size() == 4);
|
||||||
|
ASL_TEST_ASSERT(s1[0] == 1);
|
||||||
|
ASL_TEST_ASSERT(s1[1] == 2);
|
||||||
|
ASL_TEST_ASSERT(s1[2] == 3);
|
||||||
|
ASL_TEST_ASSERT(s1[3] == 4);
|
||||||
|
|
||||||
|
auto s2 = span.subspan<2>();
|
||||||
|
ASL_TEST_EXPECT(s2.size() == 2);
|
||||||
|
ASL_TEST_ASSERT(s2[0] == 3);
|
||||||
|
ASL_TEST_ASSERT(s2[1] == 4);
|
||||||
|
|
||||||
|
auto s3 = span.subspan<4>();
|
||||||
|
ASL_TEST_EXPECT(s3.size() == 0);
|
||||||
|
|
||||||
|
auto s4 = span.subspan<1, 2>();
|
||||||
|
ASL_TEST_EXPECT(s4.size() == 2);
|
||||||
|
ASL_TEST_ASSERT(s4[0] == 2);
|
||||||
|
ASL_TEST_ASSERT(s4[1] == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASL_TEST(subspan_static_from_dynamic)
|
||||||
|
{
|
||||||
|
int array[] = {1, 2, 3, 4};
|
||||||
|
asl::span<int> span{array};
|
||||||
|
|
||||||
|
auto s1 = span.subspan<0>();
|
||||||
|
ASL_TEST_EXPECT(s1.size() == 4);
|
||||||
|
ASL_TEST_ASSERT(s1[0] == 1);
|
||||||
|
ASL_TEST_ASSERT(s1[1] == 2);
|
||||||
|
ASL_TEST_ASSERT(s1[2] == 3);
|
||||||
|
ASL_TEST_ASSERT(s1[3] == 4);
|
||||||
|
|
||||||
|
auto s2 = span.subspan<2>();
|
||||||
|
ASL_TEST_EXPECT(s2.size() == 2);
|
||||||
|
ASL_TEST_ASSERT(s2[0] == 3);
|
||||||
|
ASL_TEST_ASSERT(s2[1] == 4);
|
||||||
|
|
||||||
|
auto s3 = span.subspan<4>();
|
||||||
|
ASL_TEST_EXPECT(s3.size() == 0);
|
||||||
|
|
||||||
|
auto s4 = span.subspan<1, 2>();
|
||||||
|
ASL_TEST_EXPECT(s4.size() == 2);
|
||||||
|
ASL_TEST_ASSERT(s4[0] == 2);
|
||||||
|
ASL_TEST_ASSERT(s4[1] == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASL_TEST(subspan_dynamic)
|
||||||
|
{
|
||||||
|
int array[] = {1, 2, 3, 4};
|
||||||
|
asl::span<int> span{array};
|
||||||
|
|
||||||
|
auto s1 = span.subspan(0);
|
||||||
|
ASL_TEST_EXPECT(s1.size() == 4);
|
||||||
|
ASL_TEST_ASSERT(s1[0] == 1);
|
||||||
|
ASL_TEST_ASSERT(s1[1] == 2);
|
||||||
|
ASL_TEST_ASSERT(s1[2] == 3);
|
||||||
|
ASL_TEST_ASSERT(s1[3] == 4);
|
||||||
|
|
||||||
|
auto s2 = span.subspan(2);
|
||||||
|
ASL_TEST_EXPECT(s2.size() == 2);
|
||||||
|
ASL_TEST_ASSERT(s2[0] == 3);
|
||||||
|
ASL_TEST_ASSERT(s2[1] == 4);
|
||||||
|
|
||||||
|
auto s3 = span.subspan(4);
|
||||||
|
ASL_TEST_EXPECT(s3.size() == 0);
|
||||||
|
|
||||||
|
auto s4 = span.subspan(1, 2);
|
||||||
|
ASL_TEST_EXPECT(s4.size() == 2);
|
||||||
|
ASL_TEST_ASSERT(s4[0] == 2);
|
||||||
|
ASL_TEST_ASSERT(s4[1] == 3);
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user