Skip to content

Instantly share code, notes, and snippets.

@Nekrolm
Created June 26, 2019 13:07
Show Gist options
  • Save Nekrolm/c2ac48be221a137bda224a087f7cb169 to your computer and use it in GitHub Desktop.
Save Nekrolm/c2ac48be221a137bda224a087f7cb169 to your computer and use it in GitHub Desktop.
Python-style enumerator for C++
#pragma once
#include <type_traits>
#include <utility>
#include <cstddef>
#include <algorithm>
#include <typeinfo>
#include <iterator>
template<class Range>
class Enumerator
{
public:
explicit Enumerator(Range&& range, int64_t start_with = 0)
: range_(std::forward<Range>(range)),
start_with_(start_with)
{}
template<class RangeIterator>
class enumerate_iterator{
public:
enumerate_iterator(RangeIterator&& it, int64_t id = 0) :
it_(std::forward<RangeIterator>(it)),
id_(id)
{}
auto operator* () -> std::pair<const int64_t, decltype(*std::declval<RangeIterator>())> {
return {id_, std::forward<decltype(*it_)>(*it_)};
}
auto& operator++(){
++id_;
++it_;
return *this;
}
bool operator == (const enumerate_iterator<RangeIterator>& other) const{
return it_ == other.it_;
}
bool operator != (const enumerate_iterator<RangeIterator>& other) const{
return !(*this == other);
}
private:
RangeIterator it_;
int64_t id_;
};
auto begin() {
return enumerate_iterator(std::begin(std::forward<Range>(range_)), start_with_);
}
auto end(){
return enumerate_iterator(std::end(std::forward<Range>(range_)));
}
auto cbegin() const {
return enumerate_iterator(std::cbegin(std::forward<Range>(range_)), start_with_);
}
auto cend() const {
return enumerate_iterator(std::cend(std::forward<Range>(range_)));
}
private:
int64_t start_with_ = 0;
Range range_;
};
template <class Range>
Enumerator(Range&&, size_t) -> Enumerator<Range>;
template <class Range>
Enumerator(Range&&) -> Enumerator<Range>;
#include "enumerate.h"
#include <iostream>
#include <vector>
int main()
{
for (auto [i, x] : Enumerator(std::vector<int>{1,3,4}, 5))
{
std::cout << i << " " << x << std::endl;
// ++x; compilation error
}
const std::vector<int> v = {1,2,3};
for (auto [i, x] : Enumerator(v, 5))
{
std::cout << i << " " << x << std::endl;
// ++x; // compilation error
}
std::vector<int> v2 = {1,2,3};
for (auto [i, x] : Enumerator(v2, 5))
{
std::cout << i << " " << x << std::endl;
++x; // ok icrement value in vector
}
for (auto [i, x] : Enumerator(v2, 5))
{
std::cout << i << " " << x << std::endl;
// ++x; // ok icrement value in vector
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment