Sources and Generators are the entry points to CXXIter's interface.
Sources
Sources take a given container with elements, from which a CXXIter iterator should be created. CXXIter supports three different modes of transporting elements through the iterator. (const reference / reference / move semantics). The type of the source determines which of the three options is used. For that, there exist the three sources CXXIter::SrcCRef
, CXXIter::SrcRef
, and CXXIter::SrcMov
respectively.
std::vector<float> input = {1.34f, 1.37f};
CXXIter iterator source that immutably borrows the input item source, and passes immutable references...
CXXIter iterator source that takes over the input item source, and moves its items through the elemen...
CXXIter iterator source that mutably borrows the input item source, and passes mutable references to ...
There is also the shortcut using CXXIter::from()
, which tries to determine the type of the source class to use, depending on the type of the given input parameter:
const std::vector<float> constInput = {1.34f, 1.37f};
std::vector<float> input = {1.34f, 1.37f};
constexpr SrcMov< std::remove_cvref_t< TContainer > > from(TContainer &&container)
Construct a CXXIter move source from the given container.
Supporting Custom Containers
To add support for your own container, or another container that is not yet supported, to CXXIter's sources, you need to specialize the CXXIter::SourceTrait for the container type in question. The following exemplarily shows how one would do this for the following custom container type:
template<typename TItem> struct CustomContainer {
using CustomContainerItem = TItem;
std::vector<CustomContainerItem> input;
size_t cnt = 0;
CustomContainer() {}
CustomContainer(std::initializer_list<TItem>&& initialItems) : input(std::move(initialItems)) {}
size_t size() const { return input.size(); }
CustomContainerItem& get(size_t idx) { return input.at(idx); }
const CustomContainerItem& get(size_t idx) const { return input.at(idx); }
void append(CustomContainerItem&& item) {
input.push_back(std::forward<CustomContainerItem>(item));
}
};
Specializing the CXXIter::SourceTrait for this CustomContainer
then would look like this:
template<typename TItem> struct SourceTrait<CustomContainer<TItem>> {
using Item = typename CustomContainer<TItem>::CustomContainerItem;
using IteratorState = size_t;
using ConstIteratorState = size_t;
static inline SizeHint sizeHint(const CustomContainer<TItem>& container) {
return SizeHint(container.size(), container.size());
}
static inline IteratorState initIterator(CustomContainer<TItem>&) {
return 0;
}
static inline ConstIteratorState initIterator(const CustomContainer<TItem>&) {
return 0;
}
static inline bool hasNext(CustomContainer<TItem>& container, IteratorState& iter) {
return iter < container.size();
}
static inline bool hasNext(const CustomContainer<TItem>& container, ConstIteratorState& iter) {
return iter < container.size();
}
static inline Item& next(CustomContainer<TItem>& container, IteratorState& iter) {
return container.get(iter++);
}
static inline const Item& next(const CustomContainer<TItem>& container, ConstIteratorState& iter) {
return container.get(iter++);
}
};
};
- Note
- This specialization has to be in your import context whenever you want to use a CXXIter source with
CustomContainer
, so you should probably put this in a header you can include everywhere within your project.
Generators
Generators do not take existing data containers as input of a CXXIter iterator, but instead use some kind of logic to generate elements. An example is the CXXIter::range()
generator, which takes a start
, end
and an optional step
argument, to produce numerical seriess of any arbitrary type that supports addition and comparison.
Have a look at the public methods in the CXXIter namespace for more generators and examples of how to use them.