LiteFX 0.4.1.2025
Computer Graphics Engine
|
An input range over another range, where the returned values of type T are covariants of the values stored by the underlying range. More...
#include <containers.hpp>
Public Types | |
using | value_type = std::remove_cvref_t<T> |
The type of the value that is contained by the Enumerable . | |
using | pointer = std::remove_reference_t<T>* |
The type of a pointer returned by the Enumerable . | |
using | reference = std::remove_reference_t<T>& |
The type of a reference returned by the Enumerable . | |
using | iterator = CovariantIterator<T> |
The type of the iterator used to iterate the elements of the Enumerable . | |
using | const_iterator = CovariantIterator<const std::remove_const_t<T>> |
The type of the iterator used to iterate constant elements of the Enumerable . | |
Public Member Functions | |
Enumerable () | |
Creates an enumerable over an empty range. | |
Enumerable (const Enumerable &range)=default | |
Enumerable (Enumerable &&range) noexcept=default | |
Enumerable & | operator= (const Enumerable &range)=default |
Enumerable & | operator= (Enumerable &&range) noexcept=default |
~Enumerable () noexcept=default | |
template<typename TRange , typename enabled = std::enable_if_t<!std::is_same_v<TRange, Enumerable>>> | |
Enumerable (TRange &&range) | |
Creates a new Enumerable instance from an underlying range. | |
auto | begin () const |
Returns an iterator pointing to the start of the underlying range. | |
auto | end () const |
Returns an iterator pointing to the end of the underlying range. | |
auto | cbegin () const |
Returns a constant iterator pointing to the start of the underlying range. | |
auto | cend () const |
Returns a constant iterator pointing to the end of the underlying range. | |
bool | empty () const noexcept |
Returns true , if there are no elements inside the Enumerable and false otherwise. | |
An input range over another range, where the returned values of type T are covariants of the values stored by the underlying range.
An Enumerable
is intended to be used as a covariant input range for interfaces that want to expose a range of elements that are also interfaces for the stored elements of the actual range. In the context of an Enumerable
, covariance refers to the type T either being assignable or constructible from the underlying range value type. This allows not only derived types (in a stricter definition that the C++ language standard uses), but also unrelated types, such as smart pointers to be used in a covariant fashion.
In the following example, the interface IContainer
returns an Enumerable<IContained>
from a class Container
, where the contained elements are of type Contained
.
class IContained { }; class Contained : public IContained { };
class IContainer { public: virtual Enumerable<const IContained&> elements() const noexcept = 0; };
class Container : public IContainer { private: std::vector<Contained> _elements;
public: Enumerable<const IContained&> elements() const noexcept override { return _elements; } };
As Contained
is derived from IContained
, they are covariant in terms of the language. In the context of Enumerable
, they are covariant, because a const IContained&
can be constructed from a const Contained&
. This way, using Enumeable
in IContainer
allows to iterate the interface instances without knowing their type when declaring the interface. The covariance relation only applies to the elements of the range, not the range itself. In the example above, std::vector<Contained>
is not covariant to Enumerable<const IContained>
, as the two types are not related. This is important as Enumerable
has a slight performance impact compared to returning a reference of the underlying range directly, both in terms of memory (it stores type information about the original iterators) as well as runtime (it requires a virtual call for iterator increments, dereferencing and comparison). If you want to expose covariant ranges in interfaces, but allow for maximum performance when the implementation is called directly, you can hide the interface method using private inheritance:
class IContainer { public: inline Enumerable<const IContained&> elements() const noexcept { return this->getElements(); }
private: virtual Enumerable<const IContained&> getElements() const noexcept = 0; };
class Container : public IContainer { private: std::vector<Contained> _elements;
public: const std::vector<IContained>& elements() const noexcept { return _elements; }
private: Enumerable<const IContained&> getElements() const noexcept override { return _elements; } };
Enumerable
can be using in two ways: first, it can be initialized with a lvalue reference of the underlying range or view as shown above. In this case, only the begin and end iterators of the underlying range are stored. However, when passed a rvalue reference, the Enumerable
will store the underlying range until it and all copies of it are destroyed. This allows to use Enumerable
either for returning a temporary range or a view as shown in the example below.
Enumerable<Foo> temporaryFoos() { std::vector<Foo> foos {}; foos.emplace_back(); foos.emplace_back(); foos.emplace_back();
return std::move(foos);
// Or better: //return std::vector<Foo>(3); }
Enumerable<Foo&> filteredFoos(const std::vector<Foo>& foos) { return foos | std::views::drop(1) | std::views::take(2); }
Keep in mind that the type parameter T dictates what an iterator returns from the Enumerable
, i.e. if an lvalue or (p)rvalue should be returned and wheather or not a copy is created accordingly.
T | The type of the values returned by the enumerable. |
using LiteFX::Enumerable< T >::const_iterator = CovariantIterator<const std::remove_const_t<T>> |
The type of the iterator used to iterate constant elements of the Enumerable
.
using LiteFX::Enumerable< T >::iterator = CovariantIterator<T> |
The type of the iterator used to iterate the elements of the Enumerable
.
using LiteFX::Enumerable< T >::pointer = std::remove_reference_t<T>* |
The type of a pointer returned by the Enumerable
.
using LiteFX::Enumerable< T >::reference = std::remove_reference_t<T>& |
The type of a reference returned by the Enumerable
.
using LiteFX::Enumerable< T >::value_type = std::remove_cvref_t<T> |
The type of the value that is contained by the Enumerable
.
|
inline |
Creates an enumerable over an empty range.
|
inlinedefault |
|
inlinedefaultnoexcept |
|
defaultnoexcept |
|
inline |
Creates a new Enumerable
instance from an underlying range.
TRange | The type of the underlying range. |
enabled | Disables the constructor, if TRange is equal to the current type, in which case the move constructor should be called. |
range | A reference of the underlying range. |
|
inline |
Returns an iterator pointing to the start of the underlying range.
|
inline |
Returns a constant iterator pointing to the start of the underlying range.
|
inline |
Returns a constant iterator pointing to the end of the underlying range.
|
inlinenoexcept |
Returns true
, if there are no elements inside the Enumerable
and false
otherwise.
true
, if there are no elements inside the Enumerable
and false
otherwise.
|
inline |
Returns an iterator pointing to the end of the underlying range.
|
inlinedefault |
|
inlinedefaultnoexcept |