template<unsigned dimensions, class T>
Corrade::Containers::StridedArrayView class

Multi-dimensional array view with size and stride information.

Immutable wrapper around continuous sparse range of data, useful for easy iteration over interleaved arrays and for describing multi-dimensional data. Usage example:

struct Position {
    float x, y;
};

Position positions[]{{-0.5f, -0.5f}, { 0.5f, -0.5f}, { 0.0f,  0.5f}};

Containers::StridedArrayView1D<float> horizontalPositions{positions,
    &positions[0].x, Containers::arraySize(positions), sizeof(Position)};

/* Move to the right */
for(float& x: horizontalPositions) x += 3.0f;

For convenience, similarly to ArrayView, this class is implicitly convertible from plain C arrays, ArrayView and StaticArrayView, with stride equal to array type size. The following two statements are equivalent:

int data[] { 1, 42, 1337, -69 };

Containers::StridedArrayView1D<int> a{data, 4, sizeof(int)};
Containers::StridedArrayView1D<int> b = data;

When constructing, if you don't specify the stride, the constructor assumes tightly packed data and calculates the stride automatically — stride of a dimension is stride of the next dimension times next dimension size, while last dimension stride is implicitly sizeof(T). This is especially useful for "reshaping" linear data as a multi-dimensional view. Again, the following two statements are equivalent:

int data3D[2*3*5];

Containers::StridedArrayView3D<int> a{data3D, {2, 3, 5}, {3*5*4, 5*4, 4}};
Containers::StridedArrayView3D<int> b{data3D, {2, 3, 5}};

Unlike ArrayView, this wrapper doesn't provide direct pointer access because pointer arithmetic doesn't work as usual here. The arrayCast(const StridedArrayView<dimensions, T>&) overload also works slightly differently with strided arrays — it checks that a type fits into the stride instead of expecting the total byte size to stay the same.

Multi-dimensional views

Strided array views are very useful for describing and iteration over multi-dimensional data such as 2D (sub)images. In that case, operator[]() and iterator access return a view of one dimension less instead of a direct element reference, and there are slice(const Size&, const Size&) const, prefix(const Size&) const and suffix(const Size&) const overloads working on all dimensions at the same time.

/* Sixteen 256x256 RGBA8 images */
Containers::StridedArrayView3D<std::uint32_t> images{rgbaData, {16, 256, 256}};

/* Make the center 64x64 pixels of each image opaque red */
for(auto&& image: images.slice({0, 96, 96}, {16, 160, 160}))
    for(auto&& row: image)
        for(std::uint32_t& pixel: row)
            pixel = 0xff0000ff;

Both the subscription operator and the slicing operations allow you to change the view dimension count — for example, obtaining the fifth image or just a view on the (now red) center of it. Conversely, it's possible to turn a lower-dimensional view into a slice in a higher-dimensional view.

Containers::StridedArrayView2D<std::uint32_t> image = images[5];
Containers::StridedArrayView2D<std::uint32_t> imageCenter =
    images.slice<2>({4, 96, 96}, {5, 160, 160});

Finally, since the actual view elements can be also non-scalar data, there's an overload of arrayCast(const StridedArrayView<dimensions, T>&) that can "extract" an additional dimension out of these or, on the other hand, flatten it back if the last dimension is tightly packed.

/* First dimension is Y, second X, third R/G/B/A */
Containers::StridedArrayView3D<std::uint8_t> channels =
    Containers::arrayCast<3, std::uint8_t>(image);

Utility::Debug{} << channels[128][128][1]; // green channel, 0xff

Zero and negative stride

The stride value doesn't have to be just positive. Order of elements in any dimension of the view can be reversed by calling flipped(), and together with transposed() it's possible to generate any 90° rotation of the data:

/* Bottom left before is now bottom right */
Containers::StridedArrayView2D<std::uint32_t> rotated90DegLeft =
    image.transposed<0, 1>().flipped<0>();

Setting stride to 0 in a particular dimension will reuse the same memory address for every element. The convenience broadcasted() function will repeat given dimension given number of times:

int data[8] { 0, 1, 2, 3, 4, 5, 6, 7 };

/* 8x8 array with 0–7 repeated in every row */
Containers::StridedArrayView2D<int> gradient =
    Containers::StridedArrayView1D<int>{data}.slice<2>().broadcasted<1>(8);

STL compatibility

On compilers that support C++2a and std::span, implicit conversion of it to a StridedArrayView1D is provided in Corrade/Containers/ArrayViewStlSpan.h. The conversion is provided in a separate header to avoid unconditional #include <span>, which significantly affects compile times. The following table lists allowed conversions:

Corrade typeSTL type
StridedArrayView1D<T>std::span<T>
StridedArrayView1D<T>std::span<const T, size>
StridedArrayView1D<const T>std::span<const T>

See ArrayView STL compatibility for more information.

Public types

enum (anonymous): unsigned { Dimensions = dimensions }
using Type = T
Underlying type.
using ElementType = std::conditional<dimensions==1, T&, StridedArrayView<dimensions - 1, T>>::type
Element type.
using ErasedType = std::conditional<std::is_const<T>::value, const void, void>::type
Erased type.
using Size = StridedDimensions<dimensions, std::size_t>
Size values.
using Stride = StridedDimensions<dimensions, std::ptrdiff_t>
Stride values.

Constructors, destructors, conversion operators

StridedArrayView(std::nullptr_t) constexpr noexcept
Conversion from nullptr
StridedArrayView() constexpr noexcept
Default constructor.
StridedArrayView(Containers::ArrayView<ErasedType> data, T* member, const Size& size, const Stride& stride) constexpr noexcept
Construct a view with explicit size and stride.
StridedArrayView(Containers::ArrayView<T> data, const Size& size, const Stride& stride) constexpr noexcept
Construct a view with explicit size and stride.
StridedArrayView(Containers::ArrayView<T> data, const Size& size) constexpr noexcept
Construct a view with explicit size.
template<class U, std::size_t size>
StridedArrayView(U(&data)[size]) constexpr noexcept
Construct a view on a fixed-size array.
template<class U>
StridedArrayView(StridedArrayView<dimensions, U> view) constexpr noexcept
Construct a view on StridedArrayView.
template<class U>
StridedArrayView(ArrayView<U> view) constexpr noexcept
Construct a view on ArrayView.
template<std::size_t size, class U>
StridedArrayView(StaticArrayView<size, U> view) constexpr noexcept
Construct a view on StaticArrayView.
template<class U, unsigned d = dimensions, class = typename std::enable_if<d == 1, decltype(Implementation::ArrayViewConverter<T, typename std::decay<U && >::type>::from(std::declval<U && >()))>::type>
StridedArrayView(U&& other) constexpr noexcept
Construct a view from an external view representation.
operator bool() const explicit constexpr
Whether the array is non-empty.

Public functions

auto data() const -> ErasedType* constexpr
Array data.
auto size() const -> std::conditional<dimensions==1, std::size_t, const Size&>::type constexpr
Array size.
auto stride() const -> std::conditional<dimensions==1, std::ptrdiff_t, const Stride&>::type constexpr
Array stride.
auto empty() const -> StridedDimensions<dimensions, bool> constexpr
Whether the array is empty.
auto operator[](std::size_t i) const -> ElementType
Element access.
auto begin() const -> StridedIterator<dimensions, T>
Iterator to first element.
auto cbegin() const -> StridedIterator<dimensions, T>
auto end() const -> StridedIterator<dimensions, T>
Iterator to (one item after) last element.
auto cend() const -> StridedIterator<dimensions, T>
auto front() const -> ElementType
First element.
auto back() const -> ElementType
Last element.
auto slice(std::size_t begin, std::size_t end) const -> StridedArrayView<dimensions, T>
Array slice.
template<unsigned newDimensions = dimensions>
auto slice(const Size& begin, const Size& end) const -> StridedArrayView<newDimensions, T>
Multi-dimensional array slice.
template<unsigned newDimensions = dimensions>
auto slice() const -> StridedArrayView<newDimensions, T>
Expand or shrink dimension count.
auto prefix(std::size_t end) const -> StridedArrayView<dimensions, T>
Array prefix.
template<unsigned newDimensions = dimensions>
auto prefix(const Size& end) const -> StridedArrayView<newDimensions, T>
Multi-dimensional array prefix.
auto suffix(std::size_t begin) const -> StridedArrayView<dimensions, T>
Array suffix.
template<unsigned newDimensions = dimensions>
auto suffix(const Size& begin) const -> StridedArrayView<newDimensions, T>
Multi-dimensional array suffix.
auto except(std::size_t count) const -> StridedArrayView<dimensions, T>
Array suffix.
template<unsigned newDimensions = dimensions>
auto except(const Size& count) const -> StridedArrayView<newDimensions, T>
Multi-dimensional array suffix.
auto every(std::ptrdiff_t skip) const -> StridedArrayView<dimensions, T>
Pick every Nth element.
auto every(const Stride& skip) const -> StridedArrayView<dimensions, T>
Pick every Nth element.
template<unsigned dimensionA, unsigned dimensionB>
auto transposed() const -> StridedArrayView<dimensions, T>
Transpose two dimensions.
template<unsigned dimension>
auto flipped() const -> StridedArrayView<dimensions, T>
Flip a dimension.
template<unsigned dimension>
auto broadcasted(std::size_t size) const -> StridedArrayView<dimensions, T>
Broadcast a dimension.

Enum documentation

template<unsigned dimensions, class T>
enum Corrade::Containers::StridedArrayView<dimensions, T>::(anonymous): unsigned

Enumerators
Dimensions

View dimensions

Typedef documentation

template<unsigned dimensions, class T>
typedef T Corrade::Containers::StridedArrayView<dimensions, T>::Type

Underlying type.

Underlying data type. See also ElementType and ErasedType.

template<unsigned dimensions, class T>
typedef std::conditional<dimensions==1, T&, StridedArrayView<dimensions - 1, T>>::type Corrade::Containers::StridedArrayView<dimensions, T>::ElementType

Element type.

For StridedArrayView1D equivalent to a reference to Type, for higher dimensions a strided view of one dimension less.

template<unsigned dimensions, class T>
typedef std::conditional<std::is_const<T>::value, const void, void>::type Corrade::Containers::StridedArrayView<dimensions, T>::ErasedType

Erased type.

Either void or const void based on constness of Type.

Function documentation

template<unsigned dimensions, class T>
Corrade::Containers::StridedArrayView<dimensions, T>::StridedArrayView() constexpr noexcept

Default constructor.

Creates an empty view. Copy a non-empty Array, ArrayView or StridedArrayView onto the instance to make it useful.

template<unsigned dimensions, class T>
Corrade::Containers::StridedArrayView<dimensions, T>::StridedArrayView(Containers::ArrayView<ErasedType> data, T* member, const Size& size, const Stride& stride) constexpr noexcept

Construct a view with explicit size and stride.

Parameters
data Continuous view on the data
member Pointer to the first member of the strided view
size Data size
stride Data stride

The data view is used only for a bounds check — expects that data size is enough for size and stride in the largest dimension if the stride is either positive or negative. Zero strides unfortunately can't be reliably checked for out-of-bounds conditions, so be extra careful when specifying these.

template<unsigned dimensions, class T>
Corrade::Containers::StridedArrayView<dimensions, T>::StridedArrayView(Containers::ArrayView<T> data, const Size& size, const Stride& stride) constexpr noexcept

Construct a view with explicit size and stride.

Equivalent to calling StridedArrayView(Containers::ArrayView<ErasedType>, T*, const Size&, const Stride&) with data as the first parameter and data.data() as the second parameter.

template<unsigned dimensions, class T>
Corrade::Containers::StridedArrayView<dimensions, T>::StridedArrayView(Containers::ArrayView<T> data, const Size& size) constexpr noexcept

Construct a view with explicit size.

Assuming data are contiguous, stride is calculated implicitly from size — stride of a dimension is stride of the next dimension times next dimension size, while last dimension stride is implicitly sizeof(T).

template<unsigned dimensions, class T> template<class U, std::size_t size>
Corrade::Containers::StridedArrayView<dimensions, T>::StridedArrayView(U(&data)[size]) constexpr noexcept

Construct a view on a fixed-size array.

Parameters
data Fixed-size array

Enabled only on one-dimensional views and if T* is implicitly convertible to U*. Expects that both types have the same size; stride is implicitly set to sizeof(T).

template<unsigned dimensions, class T> template<class U>
Corrade::Containers::StridedArrayView<dimensions, T>::StridedArrayView(StridedArrayView<dimensions, U> view) constexpr noexcept

Construct a view on StridedArrayView.

Enabled only if T* is implicitly convertible to U*. Expects that both types have the same size.

template<unsigned dimensions, class T> template<class U>
Corrade::Containers::StridedArrayView<dimensions, T>::StridedArrayView(ArrayView<U> view) constexpr noexcept

Construct a view on ArrayView.

Enabled only on one-dimensional views and if T* is implicitly convertible to U*. Expects that both types have the same size; stride is implicitly set to sizeof(T).

template<unsigned dimensions, class T> template<std::size_t size, class U>
Corrade::Containers::StridedArrayView<dimensions, T>::StridedArrayView(StaticArrayView<size, U> view) constexpr noexcept

Construct a view on StaticArrayView.

Enabled only on one-dimensional views and if T* is implicitly convertible to U*. Expects that both types have the same size; stride is implicitly set to sizeof(T).

template<unsigned dimensions, class T> template<class U, unsigned d = dimensions, class = typename std::enable_if<d == 1, decltype(Implementation::ArrayViewConverter<T, typename std::decay<U && >::type>::from(std::declval<U && >()))>::type>
Corrade::Containers::StridedArrayView<dimensions, T>::StridedArrayView(U&& other) constexpr noexcept

Construct a view from an external view representation.

Enabled only on one-dimensional views.

template<unsigned dimensions, class T>
std::conditional<dimensions==1, std::size_t, const Size&>::type Corrade::Containers::StridedArrayView<dimensions, T>::size() const constexpr

Array size.

Returns just std::size_t instead of Size for the one-dimensional case so the usual numeric operations work as expected. Explicitly cast to Size to ensure consistent behavior for all dimensions in generic implementations.

template<unsigned dimensions, class T>
std::conditional<dimensions==1, std::ptrdiff_t, const Stride&>::type Corrade::Containers::StridedArrayView<dimensions, T>::stride() const constexpr

Array stride.

Returns just std::ptrdiff_t instead of Stride for the one-dimensional case so the usual numeric operations work as expected. Explicitly cast to Stride to ensure consistent behavior for all dimensions in generic implementations.

template<unsigned dimensions, class T>
StridedIterator<dimensions, T> Corrade::Containers::StridedArrayView<dimensions, T>::begin() const

Iterator to first element.

template<unsigned dimensions, class T>
StridedIterator<dimensions, T> Corrade::Containers::StridedArrayView<dimensions, T>::cbegin() const

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<unsigned dimensions, class T>
StridedIterator<dimensions, T> Corrade::Containers::StridedArrayView<dimensions, T>::end() const

Iterator to (one item after) last element.

template<unsigned dimensions, class T>
StridedIterator<dimensions, T> Corrade::Containers::StridedArrayView<dimensions, T>::cend() const

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<unsigned dimensions, class T>
ElementType Corrade::Containers::StridedArrayView<dimensions, T>::front() const

First element.

Expects there is at least one element.

template<unsigned dimensions, class T>
ElementType Corrade::Containers::StridedArrayView<dimensions, T>::back() const

Last element.

Expects there is at least one element.

template<unsigned dimensions, class T>
StridedArrayView<dimensions, T> Corrade::Containers::StridedArrayView<dimensions, T>::slice(std::size_t begin, std::size_t end) const

Array slice.

Both arguments are expected to be in range. On multi-dimensional views slices just the top-level dimension.

template<unsigned dimensions, class T> template<unsigned newDimensions = dimensions>
StridedArrayView<newDimensions, T> Corrade::Containers::StridedArrayView<dimensions, T>::slice(const Size& begin, const Size& end) const

Multi-dimensional array slice.

Values in both arguments are expected to be in range for given dimension. If newDimensions is smaller than Dimensions, only the first slice is taken from the remaining dimensions; if newDimensions is larger than Dimensions, size of the new dimensions is set to 1 and and stride to size of Type.

template<unsigned dimensions, class T> template<unsigned newDimensions = dimensions>
StridedArrayView<newDimensions, T> Corrade::Containers::StridedArrayView<dimensions, T>::slice() const

Expand or shrink dimension count.

Equivalent to data.slice<newDimensions>({}, data.size()).

template<unsigned dimensions, class T>
StridedArrayView<dimensions, T> Corrade::Containers::StridedArrayView<dimensions, T>::prefix(std::size_t end) const

Array prefix.

Equivalent to data.slice(0, end). If end is 0, returns zero-sized nullptr array.

template<unsigned dimensions, class T> template<unsigned newDimensions = dimensions>
StridedArrayView<newDimensions, T> Corrade::Containers::StridedArrayView<dimensions, T>::prefix(const Size& end) const

Multi-dimensional array prefix.

Equivalent to data.slice<newDimensions>({}, end). If end is 0 in all dimensions, returns zero-sized nullptr array.

template<unsigned dimensions, class T>
StridedArrayView<dimensions, T> Corrade::Containers::StridedArrayView<dimensions, T>::suffix(std::size_t begin) const

Array suffix.

Equivalent to data.slice(begin, data.size()[0]).

template<unsigned dimensions, class T> template<unsigned newDimensions = dimensions>
StridedArrayView<newDimensions, T> Corrade::Containers::StridedArrayView<dimensions, T>::suffix(const Size& begin) const

Multi-dimensional array suffix.

Equivalent to data.slice<newDimensions>(begin, data.size()).

template<unsigned dimensions, class T>
StridedArrayView<dimensions, T> Corrade::Containers::StridedArrayView<dimensions, T>::except(std::size_t count) const

Array suffix.

Equivalent to data.slice({}, data.size()[0] - count).

template<unsigned dimensions, class T> template<unsigned newDimensions = dimensions>
StridedArrayView<newDimensions, T> Corrade::Containers::StridedArrayView<dimensions, T>::except(const Size& count) const

Multi-dimensional array suffix.

Equivalent to data.slice<newDimensions>({}, end), where end is data.size()[i] - count[i] for all dimensions.

template<unsigned dimensions, class T>
StridedArrayView<dimensions, T> Corrade::Containers::StridedArrayView<dimensions, T>::every(std::ptrdiff_t skip) const

Pick every Nth element.

Multiplies stride() with skip and adjusts size() accordingly. Negative skip is equivalent to first calling flipped() and then this function with a positive value. On multi-dimensional views affects just the top-level dimension.

template<unsigned dimensions, class T>
StridedArrayView<dimensions, T> Corrade::Containers::StridedArrayView<dimensions, T>::every(const Stride& skip) const

Pick every Nth element.

Multiplies stride() with skip and adjusts size() accordingly. Negative skip is equivalent to first calling flipped() and then this function with a positive value.

template<unsigned dimensions, class T> template<unsigned dimensionA, unsigned dimensionB>
StridedArrayView<dimensions, T> Corrade::Containers::StridedArrayView<dimensions, T>::transposed() const

Transpose two dimensions.

Exchanges dimensions dimensionA and dimensionB by swapping their size and stride values. Together with flipped() can be used to do arbitrary 90° rotations of the view. This is a non-destructive operation on the view, transposing it again will go back to the original form.

template<unsigned dimensions, class T> template<unsigned dimension>
StridedArrayView<dimensions, T> Corrade::Containers::StridedArrayView<dimensions, T>::flipped() const

Flip a dimension.

Flips given dimension by making its stride negative and adjusting the internal base data pointer. Together with transposed() can be used to do arbitrary 90° rotations of the view. This is a non-destructive operation on the view, flipping it again will go back to the original form.

template<unsigned dimensions, class T> template<unsigned dimension>
StridedArrayView<dimensions, T> Corrade::Containers::StridedArrayView<dimensions, T>::broadcasted(std::size_t size) const

Broadcast a dimension.

Stretches the initial value to size in given dimension by setting its stride to 0 and size to size. To avoid destructive operations on the view, the function expects that size in given dimension is 1. If you need to broadcast a dimension that has more elements, slice() it first.

template<unsigned dimensions, class T> template<std::size_t size, class T>
StridedArrayView1D<T> stridedArrayView(T(&data)[size]) constexpr

Make a strided view on fixed-size array.

Convenience alternative to StridedArrayView::StridedArrayView(U(&)[size]). The following two lines are equivalent:

std::uint32_t data[15];

Containers::StridedArrayView1D<std::uint32_t> a{data};
auto b = Containers::stridedArrayView(data);

template<unsigned dimensions, class T> template<class T>
StridedArrayView1D<T> stridedArrayView(ArrayView<T> view) constexpr

Make a strided view on ArrayView.

Convenience alternative to StridedArrayView::StridedArrayView(ArrayView<U>). The following two lines are equivalent:

Containers::ArrayView<std::uint32_t> data;

Containers::StridedArrayView1D<std::uint32_t> a{data};
auto b = Containers::stridedArrayView(data);

template<unsigned dimensions, class T> template<std::size_t size, class T>
StridedArrayView1D<T> stridedArrayView(StaticArrayView<size, T> view) constexpr

Make a strided view on StaticArrayView.

Convenience alternative to StridedArrayView::StridedArrayView(StaticArrayView<size, U>). The following two lines are equivalent:

Containers::StaticArrayView<15, std::uint32_t> data;

Containers::StridedArrayView1D<std::uint32_t> a{data};
auto b = Containers::stridedArrayView(data);

template<unsigned dimensions, class T> template<unsigned dimensions, class T>
StridedArrayView<dimensions, T> stridedArrayView(StridedArrayView<dimensions, T> view) constexpr

Make a view on a view.

Equivalent to the implicit StridedArrayView copy constructor — it shouldn't be an error to call stridedArrayView() on itself.

template<unsigned dimensions, class T> template<class T, class U = decltype(stridedArrayView(Implementation::ErasedArrayViewConverter<typename std::remove_reference<T && >::type>::from(std::declval<T && >())))>
U stridedArrayView(T&& other) constexpr

Make a strided view on an external type / from an external representation.

template<unsigned dimensions, class T> template<class U, unsigned dimensions, class T>
StridedArrayView<dimensions, U> arrayCast(const StridedArrayView<dimensions, T>& view)

Reinterpret-cast a strided array view.

Size of the new array is the same as original. Expects that both types are standard layout and sizeof(U) is not larger than any stride() of the original array. Works with negative and zero strides as well, however note that no type compatibility checks can be done for zero strides, so be extra careful in that case.

struct Pixel {
    std::uint8_t r, g, b, a;
};

Pixel pixels[]{{0x33, 0xff, 0x99, 0x66}, {0x11, 0xab, 0x33, 0xff}};

auto red = Containers::StridedArrayView1D<std::uint8_t>{pixels, &pixels[0].r, 2, 4};
auto rgba = Containers::arrayCast<Pixel>(red);

template<unsigned dimensions, class T> template<unsigned newDimensions, class U, unsigned dimensions, class T>
StridedArrayView<newDimensions, U> arrayCast(const StridedArrayView<dimensions, T>& view)

Reinterpret-cast and flatten or inflate a strided array view.

If newDimensions is one less than dimensions, flattens the last dimension into a tightly packed new type U, expecting the last dimension to be tightly packed and its stride equal to size of U. If newDimensions is one more than dimensions, inflates the last dimension into the new type U, its element count being ratio of T and U sizes. This operation can be used for example to peek into individual channels pixel data:

struct Rgb {
    std::uint8_t r, g, b;
};

Containers::ArrayView<Rgb> pixels;

Containers::StridedArrayView2D<Rgb> view{pixels, {128, 128}};
Containers::StridedArrayView3D<std::uint8_t> rgb =
    Containers::arrayCast<3, std::uint8_t>(view);