https://github.com/thelartians/easyiterator
🏃 Iterators made easy! Zero cost abstractions for designing and using C++ iterators.
https://github.com/thelartians/easyiterator
advance algorithms benchmark boilerplate cplusplus cpp enumerate iterator iterators loops next pythonic range reverse simple
Last synced: about 1 month ago
JSON representation
🏃 Iterators made easy! Zero cost abstractions for designing and using C++ iterators.
- Host: GitHub
- URL: https://github.com/thelartians/easyiterator
- Owner: TheLartians
- License: mit
- Created: 2019-05-07T14:56:12.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2024-10-14T15:33:27.000Z (about 1 year ago)
- Last Synced: 2025-05-18T07:03:31.430Z (6 months ago)
- Topics: advance, algorithms, benchmark, boilerplate, cplusplus, cpp, enumerate, iterator, iterators, loops, next, pythonic, range, reverse, simple
- Language: C++
- Homepage:
- Size: 85 KB
- Stars: 143
- Watchers: 6
- Forks: 8
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://github.com/TheLartians/EasyIterator/actions)
[](https://github.com/TheLartians/EasyIterator/actions)
[](https://github.com/TheLartians/EasyIterator/actions)
[](https://github.com/TheLartians/EasyIterator/actions)
[](https://github.com/TheLartians/EasyIterator/actions)
[](https://codecov.io/gh/TheLartians/EasyIterator)
# EasyIterator
C++ iterators and range-based loops are incredibly useful, however defining iterators still requires a large amount of boilerplate code.
The goal of this library is to find alternative and useful ways to use and create C++17 iterators without impacting performance or compiler optimizations.
## Example
### Iteration
EasyIterator adds well-known generators and iterator combinators from other languages to C++, such as `range`, `zip` and `enumerate`.
```cpp
using namespace easy_iterator;
std::vector integers(10);
std::vector strings(integers.size());
for (auto i: range(integers.size())) {
integers[i] = i*i;
}
for (auto [i, v, s]: zip(range(integers.size()), integers, strings)) {
s = std::to_string(i) + "^2 = " + std::to_string(v);
}
for (auto [i, s]: enumerate(strings)) {
std::cout << "strings[" << i << "] = \"" << s << "\"" << std::endl;
}
```
### Iterator definition
Most iterator boilerplate code is defined in an `easy_iterator::IteratorPrototype` base class type.
A possible implementation of the `range` iterable is below.
```cpp
using namespace easy_iterator;
template struct RangeIterator: public IteratorPrototype {
T increment;
RangeIterator(const T &start):
IteratorPrototype(start),
increment(1) {
}
RangeIterator &operator++(){ RangeIterator::value += increment; return *this; }
};
template auto range(T end) {
return wrap(RangeIterator(begin), RangeIterator(end));
}
```
### Iterable algorithms
Algorithms can be easily wrapped into iterators by defining a class that defines `advance()` and `value()` member functions. The code below shows how to define an iterator over Fibonacci numbers.
```cpp
struct Fibonacci {
unsigned current = 0;
unsigned next = 1;
void advance() {
auto tmp = next;
next += current;
current = tmp;
}
unsigned value() {
return current;
}
};
using namespace easy_iterator;
for (auto [i,v]: enumerate(MakeIterable())){
std::cout << "Fib_" << i << "\t= " << v << std::endl;
if (i == 10) break;
}
```
Algorithms that have an end state can also be defined by returning a the state in the `advance()` method. If the initial state can also be undefined, the iterator should define a `bool init()` method and inherit from `easy_iterator::InitializedIterable`. The code below shows an alternative `range` implementation.
```cpp
template struct RangeIterator: public easy_iterator::InitializedIterable {
T current, max, step;
RangeIterator(T end): current(0), max(end), step(1) { }
bool advance(){ current += step; return current != max; }
bool init(){ return current != max; }
T value(){ return current; }
};
template auto range(T end) {
return easy_iterator::MakeIterable>(end);
}
```
## Installation and usage
EasyIterator is a single-header library, so you can simply download and copy the header into your project, or use the Cmake script to install it globally.
Using the [CPM](https://github.com/cpm-cmake/CPM.cmake) dependency manager, you can also include EasyIterator simply by adding the following to your projects' `CMakeLists.txt`.
```cmake
CPMAddPackage("gh:thelartians/easyiterator@1.5")
target_link_libraries(myProject EasyIterator)
set_target_properties(myProject PROPERTIES CXX_STANDARD 17)
```
## Test suite
You can run the tests suite included in this repo with the following commands.
```bash
cmake -Htest -Bbuild/test
cmake --build build/test
cmake --build build/test --target test
```
## Performance
EasyIterator is designed to come with little or no performance impact compared to handwritten code. For example, using `for(auto i: range(N))` loops create identical assembly compared to regular `for(auto i=0;i