slice
Introduction
The slice represents a view of a contiguous sequence of elements while providing a friendly container-like interface to work with said elements. This means that slice doesn’t own the data it refers to. slice internally stores information about the beginning of a container (pointer to the first element of a sequence) and the number of elements to refer to (size), which means that the data must live longer than the slice itself.
Origin: slice is almost identical to std::span,
which was introduced in C++20 and before that it was available in C++14 with help of
Guideline Support Library gsl::span
.
estd::slice
is your go-to type when you want to refer to containers in your API.
Usage
The usage guidelines apply for slice.
Constraints
Static slice having size greater than the container, cannot be created. Compilation error will be thrown if attempt to create is made.
Usage guidance
Size of the slice should be checked before accessing the elements. Accessing outside the bounds of slice using
at<>()
will result in compilation error. and usingat()
,operator[]()
function will result in an assertion. Size of the slice should be checked before trying to create subslice from a slice of size ‘Size’. Calling ‘subslice<Limit>()’ with Limit > Size and ‘offset<Offset>() with Offset >= Size will result in compilation error. Calling subslice(limit) with limit > Size and offset(position) with position >= Size will return zero length slice.
Example
Example below shows how to construct static estd::slice from C array. Here the size of slice is known at compile-time :
uint8_t data[] = {0, 1, 2, 3, 4};
// statically-sized slice of size 5
::estd::slice<uint8_t, 5U> slice5(data);
// statically-sized slice of size 3 which points to the first three elements
::estd::slice<uint8_t, 3U> slice3(data);
Example below shows how to construct variable length estd::slice from C array. Here the size of the slice is variable :
uint8_t data[] = {0, 1, 2, 3, 4};
// dynamically-sized slice of size 5
::estd::slice<uint8_t> dynSizeSlice(data);
// dynamically-sized slice can be constructed from a statically sized slice:
::estd::slice<uint8_t, 5U> slice5(data);
The next example shows constructing slice from estd::array :
::estd::array<int32_t, 4U> data = {0, 1, 2, 3};
::estd::slice<int32_t, 4U> slice4(data);
The next example shows constructing dynamic slice from estd::vector :
::estd::declare::vector<int32_t, 10> v1;
::estd::slice<int32_t> s1(v1);
::estd::declare::vector<int32_t, 20> v2;
::estd::vector<int32_t>& v3 = v2;
::estd::slice<int32_t> s3(v3);
Below is an example of how slice can be constructed from a pointer to an array.
uint8_t data[] = {0, 1, 2, 3, 4};
uint8_t* pointer = data;
::estd::slice<uint8_t, 5U> slice5_fp = ::estd::slice<uint8_t, 5U>::from_pointer(pointer);
Note that it’s not possible to construct a slice with size greater than a data it refers to. The following code won’t compile.
::estd::slice<uint8_t, 6U> slice6(data); // won't compile - array is smaller than the size of slice
Example below shows how to construct estd::slice from non-Member functions like make_str(), make_slice(), make_static_slice() :
uint32_t data[] = {0, 1, 2, 3, 4};
auto staticSlice = ::estd::make_static_slice(data); // staticSlice has type slice<uint32_t, 5>
The below example shows the ways to iterate through the slice :
uint32_t data[] = {0, 1, 2, 3, 4};
::estd::slice<uint32_t> slice5{data};
// iterate over all elements, incrementing each of them:
for (auto& i : slice5)
{
++i;
}
// iterate over elements in reverse order
for (auto rev_it = slice5.rbegin(); rev_it != slice5.rend(); ++rev_it)
{
*rev_it = *rev_it + 10;
}
The below example shows how to access the data of slice with ‘at<Index>()’ function :
uint8_t data[] = {0, 1, 2, 3, 4};
::estd::slice<uint8_t, 5> const slice5(data);
slice5.at<0>() = 42; // assign 42 to the first element
The next example shows creating a subslice from another slice (subview) :
uint8_t data[] = {0, 1, 2, 3, 4};
::estd::slice<uint8_t> const slice(data);
The next example shows creating a subslice from another slice with a compile time size (static subview) :
uint8_t data[] = {0, 1, 2, 3, 4};
::estd::slice<uint8_t, 5U> const slice5(data);
::estd::slice<uint8_t, 4U> slice4 = slice5.offset<1>(); // skip 1 element: {1, 2, 3, 4}
::estd::slice<uint8_t, 3U> slice3 = slice5.subslice<3>(); // first 3 elements: {0, 1, 2}
The next example shows remapping the slice to another area of the container with advance(), trim() function :
uint8_t data[] = {0, 1, 2, 3, 4};
::estd::slice<uint8_t> slice(data);
slice.advance(1U); // slice's pointer incremented by one, now points to {1, 2, 3, 4}
slice.trim(2U); // slice's size decreased to 2, now points to {1, 2}