0

The following code is a naive implementation of a solution to a problem in which a 2D vector of 1's and 0's are inputted to some function closedIsland where 1's in some column and row represent water and 0's represent land. The aim of the algorithm is to find the number of 'closed islands' which are pieces of land surrounded by water. I am using iterators to loop over the vector and I have written a helper function called checkSurroundings to implement some logic checks for specific cases. For brevity sake, I have excluded all but one of the cases. It is in this function which my error occurs.

#include <vector>

 bool checkSurroundings(std::vector<std::vector<int>>::iterator col_it,std::vector<int>::iterator row_it, int index_column, int index_row, int max_row_size, int max_col_size){
        bool is_surrounded = false; 
        switch(index_column){
            case 0: 
                col_it++; 
                switch(index_row){
                    case 0:
                        if(*(row_it+1)==1 && *(col_it)[index_row]==1) //error here
                            is_surrounded = true; 
                        break;
                   //other cases follow
                }
                break;
//other cases follow
}
}

int closedIsland(std::vector<std::vector<int>>& grid) {
    int max_column_size = grid.size(); 
    int max_row_size = grid[0].size(); 
    int closed_island_count = 0; 
    bool is_surrounded = false;

    for(std::vector<std::vector<int>>::iterator column_it = grid.begin(); column_it!=grid.end(); column_it+1){
        for(std::vector<int>::iterator row_it = column_it->begin(); row_it!= column_it->end(); row_it+1){
            auto index_column = std::distance(column_it,grid.end());
            auto index_row = std::distance(row_it,column_it->end());

            if(*row_it == 0){
                is_surrounded = checkSurroundings(column_it,row_it,index_column,index_row,max_row_size,max_column_size); 
                if(is_surrounded)
                    closed_island_count++;
            }
        }
    }
    return closed_island_count; 
}

The code above compiles (apart from the error) using g++ -std=c++17

I am running into the following error:

error: indirection requires pointer operand ('std::vector<int, std::allocator>' invalid) if(*(row_it+1)==1 && *(col_it)[index_row]==1)

I was expecting this to work by the following logic: col_it is a vector<vector<int>>::iterator type so dereferncing the iterator *(col_it) should give me the vector<vector<int>> itself and by using [] notation I should be able to access the inner vector. Why does this not work in this case?

Blargian
  • 294
  • 3
  • 14
  • 1
    It is in your best interests to provide an example that compiles other than the one error you're asking about. This allows us to look at the problem from different directions with no distractions and toss the code into other compilers to see if they provide better diagnostics, something helpful for you to do as well. – user4581301 Apr 06 '23 at 17:12
  • 2
    `*(col_it)[index_row]` is parsed as `*(col_it[index_row])`, not `(*col_it)[index_row]`. If you want the latter you need to move your `()`. – Miles Budnek Apr 06 '23 at 17:14
  • What's the purpose of the iterators there? Are you planning to remove any element from the vector or something? If not, it's better accessing the elements by their indices or just using a [range based for](https://en.cppreference.com/w/cpp/language/range-for). – Mateo Apr 06 '23 at 17:14
  • @Mateo I want to use them as pointers to the data essentially. If you imagine a 9x9 square. If I'm looking at an element in the middle I want to be able to say `col_itr--` to get the column behind or `row_itr++` to get the block to the right, `row_itr--` to get the block to the left etc. Probably there are better ways to do it, it's just what I came up with at the time. I'm not planning to remove anything. – Blargian Apr 06 '23 at 17:23
  • Syntax errors usually require at most half a dozen lines to demonstrate. Why is your [mre] more complex than `#include bool checkSurroundings(std::vector>::iterator col_it, int index_row) { return *(col_it)[index_row]==1; //error here }`? (Isolate the sub-expression with the error, and strip away almost everything else.) You were trying to demonstrate the error, not to demonstrate how to check surroundings, right? – JaMiT Apr 07 '23 at 08:43
  • Some similar questions (that I found by searching for the answer, so not surprising for an asker to not find them): [1](https://stackoverflow.com/q/64866353) - [2](https://stackoverflow.com/q/63949182) - [3](https://stackoverflow.com/q/55819573) - [4](https://stackoverflow.com/q/44575307) - [5](https://stackoverflow.com/q/41062985) - [6](https://stackoverflow.com/q/40360301) - [7](https://stackoverflow.com/q/32185483) - [8](https://stackoverflow.com/q/24202737) - [9](https://stackoverflow.com/q/18420183) - [0xA](https://stackoverflow.com/q/8809435) – JaMiT Apr 07 '23 at 09:10

1 Answers1

3

It all comes down to operator precedence: Since the subscript operator ([]) has a higher precedence than the unary * operator, the expression

*(col_it)[index_row]

is evaluated as

*(col_it[index_row])

, not as

(*col_it)[index_row]

. The subscript operator applied to a expression of type vector<vector<int>>::iterator yields a reference to vector<int> and for an expression of this type the unary * operator is not implemented resulting in the compiler error observed.

fabian
  • 80,457
  • 12
  • 86
  • 114