template<class T>
Corrade::Containers::Iterable class new in Git master

Wrapper for any sequential container of values or references.

Useful in scenarios where, given a heavy or a move-only T, it's desirable to have an API accept ArrayView<const Reference<T>> to account for cases where instances are scattered around and can't be put into a linear container, but also accept just plain ArrayView<T> and other variants for convenience.

This class adds extra indirection to allow iterating over various input containers with a single code path. Assuming the API itself isn't bottlenecked on iteration performance, it should be an acceptable tradeoff compared to having to implement multiple code paths or have extra overloads that unify the process by copying the data to a temporary container first. In contrast, if the type doesn't need to be taken via a reference, it's preferable to accept just ArrayView<T> or StridedArrayView*D<T> instead of using this class.

Usage

An Iterable<T> can be implicitly created from an ArrayView<T>, StridedArrayView1D<T>; (strided) array view of (const) Reference<T>, MoveReference<T> or AnyReference<T>; std::initializer_list; and any other type convertible to these. Such as plain C arrays, Array or STL types convertible to an ArrayView.

Example usage — passing a list of non-copyable Utility::FileWatcher instances to an API:

void foo(const Containers::Iterable<Utility::FileWatcher>&);

Utility::FileWatcher a{}, b{};
Utility::FileWatcher cArray[3]{};
Containers::Array<Containers::Reference<Utility::FileWatcher>> array{};
std::vector<Utility::FileWatcher> vector{};

foo({a, b}); /* passing (references to) variables directly */
foo(cArray); /* passing a C array */
foo(array);  /* passing an array of references */
foo(vector); /* passing a STL vector */

On the API implementation side, the usual container interface is exposed — in particular isEmpty(), size(), operator[](), front(), back() as well as range-for access:

void foo(const Containers::Iterable<Utility::FileWatcher>& watchers) {
    for(Utility::FileWatcher& watcher: watchers) {
        
    }
}

Public types

using Type = T
Element type.

Constructors, destructors, conversion operators

Iterable(std::nullptr_t = nullptr) constexpr noexcept
Default constructor.
template<class U, class = decltype(Iterable{std::declval<U && >(), Implementation::IterableOverloadPriority<1>{}})>
Iterable(U&& data) noexcept
Construct from any sequential iterable container.
Iterable(std::initializer_list<AnyReference<T>> view) noexcept
Construct from an initializer list.
template<class U = typename std::remove_const<T>::type, class = typename std::enable_if<!std::is_same<T, U>::value>::type>
Iterable(std::initializer_list<AnyReference<typename std::remove_const<T>::type>> view) noexcept
Iterable(const void* data, std::size_t size, std::ptrdiff_t stride, T&(*)(const void*) accessor) explicit noexcept
Construct a custom iterable.

Public functions

auto data() const -> const void*
Data pointer.
auto size() const -> std::size_t
Number of items in the container.
auto stride() const -> std::ptrdiff_t
Stride between items in the container.
auto isEmpty() const -> bool
Whether the container is empty.
auto operator[](std::size_t i) const -> T&
Element access.
auto begin() const -> IterableIterator<T>
Iterator to first element.
auto cbegin() const -> IterableIterator<T>
auto end() const -> IterableIterator<T>
Iterator to (one item after) last element.
auto cend() const -> IterableIterator<T>
auto front() const -> T&
First element.
auto back() const -> T&
Last element.

Function documentation

template<class T>
Corrade::Containers::Iterable<T>::Iterable(std::nullptr_t = nullptr) constexpr noexcept

Default constructor.

Creates an instance with nullptr data and size and stride set to 0.

template<class T> template<class U, class = decltype(Iterable{std::declval<U && >(), Implementation::IterableOverloadPriority<1>{}})>
Corrade::Containers::Iterable<T>::Iterable(U&& data) noexcept

Construct from any sequential iterable container.

U can be an ArrayView<T>, StridedArrayView1D<T>; (strided) array view of (const) Reference<T>, MoveReference<T> or AnyReference<T>; and any other type convertible to these — see ArrayView and StridedArrayView docs for more information.

template<class T>
Corrade::Containers::Iterable<T>::Iterable(std::initializer_list<AnyReference<T>> view) noexcept

Construct from an initializer list.

In order to be able to accept also lists of non-copyable types, the constructor takes a reference type. Then, to accept both {a, b, c} and {T{}, T{}, T{}}, it's an AnyReference instead of a Reference.

template<class T> template<class U = typename std::remove_const<T>::type, class = typename std::enable_if<!std::is_same<T, U>::value>::type>
Corrade::Containers::Iterable<T>::Iterable(std::initializer_list<AnyReference<typename std::remove_const<T>::type>> view) noexcept

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

template<class T>
Corrade::Containers::Iterable<T>::Iterable(const void* data, std::size_t size, std::ptrdiff_t stride, T&(*)(const void*) accessor) explicit noexcept

Construct a custom iterable.

Parameters
data Container data pointer
size Number of items in the container
stride Stride between items in the container
accessor Accessor function

For item i, the accessor gets data + i*stride in the argument.

template<class T>
const void* Corrade::Containers::Iterable<T>::data() const

Data pointer.

Not meant to be used directly, as the returned value may point to an actual value but also to a reference to the value, with no possibility to distinguish between the two. The returned pointer is const even when T is mutable as the data may point to const Reference<T> and similar.

template<class T>
std::size_t Corrade::Containers::Iterable<T>::size() const

Number of items in the container.

template<class T>
std::ptrdiff_t Corrade::Containers::Iterable<T>::stride() const

Stride between items in the container.

For a contiguous array of T it's equal to sizeof(T), for references it's sizeof(void*), for a strided view it's equivalent to StridedArrayView::stride().

template<class T>
bool Corrade::Containers::Iterable<T>::isEmpty() const

Whether the container is empty.

template<class T>
T& Corrade::Containers::Iterable<T>::operator[](std::size_t i) const

Element access.

Expects that i is less than size().

template<class T>
IterableIterator<T> Corrade::Containers::Iterable<T>::begin() const

Iterator to first element.

template<class T>
IterableIterator<T> Corrade::Containers::Iterable<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<class T>
IterableIterator<T> Corrade::Containers::Iterable<T>::end() const

Iterator to (one item after) last element.

template<class T>
IterableIterator<T> Corrade::Containers::Iterable<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<class T>
T& Corrade::Containers::Iterable<T>::front() const

First element.

Expects there is at least one element.

template<class T>
T& Corrade::Containers::Iterable<T>::back() const

Last element.

Expects there is at least one element.