-2

In Python , instead of

colors = ['red', 'green', 'blue', 'yellow']

for i in range(len(colors)):
    print i, '--->', colors[i]

One can write

for i, color in enumerate(colors):
    print i, '--->', color

Is there a similar thing in c++?

athos
  • 6,120
  • 5
  • 51
  • 95
  • I don't think so. If you iterate over a `std::vector`, it just gives you the elements, not the indexes. – Barmar Dec 23 '17 at 00:25
  • Possible duplicate of [What is the most effective way to get the index of an iterator of an std::vector?](https://stackoverflow.com/questions/2152986/what-is-the-most-effective-way-to-get-the-index-of-an-iterator-of-an-stdvector) – Barmar Dec 23 '17 at 00:27

3 Answers3

1

Boost provides an adaptor which allows to do something similiar:

http://www.boost.org/doc/libs/1_63_0/libs/range/doc/html/range/reference/adaptors/reference/indexed.html

The following code is taken from the link above

#include <boost/range/adaptor/indexed.hpp>
#include <boost/assign.hpp>
#include <iterator>
#include <iostream>
#include <vector>

int main(int argc, const char* argv[])
{
    using namespace boost::assign;
    using namespace boost::adaptors;

    std::vector<int> input;
    input += 10,20,30,40,50,60,70,80,90;

    for (const auto& element : input | indexed(0))
    {
        std::cout << "Element = " << element.value()
                  << " Index = " << element.index()
                  << std::endl;
    }

    return 0;
}
Omni
  • 1,002
  • 6
  • 12
1

Maybe you can emulate it like this:

int i = 0;
for (auto color : { "red", "green", "blue", "yellow" })
    std::cout << i++ << "--->" << color << std::endl;
Killzone Kid
  • 6,171
  • 3
  • 17
  • 37
  • and now run this function two times and you'll get 4,5,6,7 instead of indexes – RiaD Dec 23 '17 at 00:44
  • @RiaD this is not a function – Killzone Kid Dec 23 '17 at 00:55
  • 1
    @KillzoneKid No, but this code must be put inside a function somewhere, and when it does, the `static` will cause issues on repeated invocations of the function. Just remove the `static` keyword and move your `i` initialisation to before the loop. – hnefatl Dec 23 '17 at 00:56
1

You can actually implement something similar in c++17.

Here is a sketch(c++-ish pseudocode), I use values everywhere and they should be replaced by appropriate references/forwarding, also you should fix how you get types (use iterator_traits), may be support unknown size, may be implement proper iterator interface etc

template <typename T>
struct EnumeratedIterator {
    size_t index;
    T iterator;
    void operator++() {
        ++iterator;
    }
    std::pair<size_t, T>() {
        return {index, *iterator};
    }
    bool operator !=(EnumeratedIterator o) {
        return iterator != o.iterator;
    }
}

template <typename T>
struct Enumerated {
    T collection;
    EnumeratedIterator<typename T::iterator> begin() {
        return {0, collection.begin()};
    }
    EnumeratedIterator<typename T::iterator> end() {
        return {collection.size(), collection.end()};
    }
}

auto enumerate(T col) {
    return Enumerated<T>(col);
}

and then use it like

for (auto [index, color] : enumerate(vector<int>{5, 7, 10})) {
    assert(index < color);
}
RiaD
  • 46,822
  • 11
  • 79
  • 123