Skip to content

Instantly share code, notes, and snippets.

@jdiego
Last active November 25, 2018 22:58
Show Gist options
  • Save jdiego/f5d51fcbf27d519a7c9dd2fa18737b78 to your computer and use it in GitHub Desktop.
Save jdiego/f5d51fcbf27d519a7c9dd2fa18737b78 to your computer and use it in GitHub Desktop.
Python-Like enumerate() In C++17
#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)};
}
@jdiego
Copy link
Author

jdiego commented Nov 25, 2018

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:

#include "enumerate.hpp"
#include <iostream>
#include <string>
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;
    }
    return 0;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment