Search code examples
c++for-loopstdvector

iteration through a very, very long std::vector question


I have a std::vector<std::tuple<int, int>> which shall be able to accommodate potentially very many elements.

I do not know in advance how many elements it will have. It depends on how I run my code (with what input parameters).

I want to iterate over this vector.

At the moment, I am doing:

for (long long int idx = 0; idx <= (vec.size() - 1); idx++) {
    do_something(vec[idx]);
}

This produces the warning: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<std::tuple<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]

From SO, I understand that vec.size() returns a std::vector<std::tuple<int, int> >::size_type, which I understand that it potentially can not be the same as size_t: https://stackoverflow.com/a/28514377/12248220

My question is: How shall I write the for-loop to iterate through all the elements of the vector, without warnings?

For example, an int is not enough, I am sure the vector will hold more than 65535 elements.

Also, long unsigned int, what the compiler tells me that .size() returns, might be not enough to hold all the elements of my vector: from https://en.cppreference.com/w/cpp/language/types, it seems that it can go up to 4,294,967,295 only.

4 294 967 295 * 8 bytes = 34.3597384 gigabytes according to google, and yes, I do have more RAM than this (I am on a HPC server with 128 GB of ram per node).

This question can be also posed for a vector of ints only, there the multiplication above will be performed as 4 294 967 295 * 4 bytes ...

Thank you!


Solution

  • I understand that vec.size() returns a std::vector<std::tuple<int, int>>::size_type

    So use it:

    for (decltype(vec.size()) i = 0; i < vec.size(); ++i) {
        do_something(vec[i]);
    }
    

    You can also make am explicit type alias:

    using IndexType = std::vector<std::tuple<int, int>>::size_type;
    for (IndexType i = 0; i < vec.size(); ++i) { ... }
    

    Or use a range-based for loop, optionally with an index on the side:

    decltype(vec.size()) i = 0;
    for (auto& value : vec) { // may be `auto const&` or even just `auto`
        do_something(value, i);
        ++i;
    }
    

    Or use iterators directly:

    for (auto it = vec.begin(); it != vec.end(); ++it) {
        // std::distance is constant-time with std::vector iterators (basically just `it - vec.begin()`)
        auto i = std::distance(vec.begin(), it);
        do_something(*it, i);
    }
    

    Demo