Last active
November 25, 2018 22:58
-
-
Save jdiego/f5d51fcbf27d519a7c9dd2fa18737b78 to your computer and use it in GitHub Desktop.
Python-Like enumerate() In C++17
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <tuple> | |
/* | |
Example of use: | |
int main(void) | |
{ | |
std::vector<std::string> things = {"Hello", "World", "!"}; | |
for (auto [i, thing] : enumerate(things)) | |
{ | |
std::cout << "The " << i << "th thing is " << thing << std::endl; | |
} | |
} | |
*/ | |
template | |
< | |
typename Type, | |
typename Iter = decltype(std::begin(std::declval<Type>())), | |
typename = decltype(std::end(std::declval<Type>())) | |
> | |
constexpr auto enumerate(Type&& iterable) | |
{ | |
struct iterator | |
{ | |
size_t i; | |
Iter iter; | |
bool operator !=(const iterator& other) const | |
{ | |
return iter != other.iter; | |
} | |
void operator++(void) | |
{ | |
++i; | |
++iter; | |
} | |
auto operator* (void) const | |
{ | |
return std::tie(i, *iter); | |
} | |
}; | |
struct iterable_wrapper | |
{ | |
Type iterable; | |
auto begin(void) | |
{ | |
return iterator{0, std::begin(iterable) }; | |
} | |
auto end(void) | |
{ | |
return iterator{0, std::end(iterable) }; | |
} | |
}; | |
return iterable_wrapper {std::forward<Type>(iterable)}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Python has a handy built-in function called enumerate(), which lets you iterate over an object (e.g. a list) and have access to both the index and the item in each iteration. You use it in a for loop, like this:
for i, thing in enumerate(things):
print("The %dth thing is %s" % (i, thing))
Iterating over things directly would give you thing, but not i, and there are plenty of situations where you’d want both (looking up the index in another data structure, progress reports, error messages, generating output filenames, etc).
So, in C++ 17, we can implement enumerate() by creating an iterable object that wraps another iterable and generates the indices during iteration. Then we can use it like this: