Getting reference of dereferenced element from container of pointers by ranged loop

543 Views Asked by At

Given a container of pointers to ints, how can I increment the ints without using a dereference operator * within the loop body {}?

Here's the implementation with the dereference operator in the loop body:

#include <vector>
#include <iostream>
using namespace std;

int main() {
    int x = 0, y = 1, z = 2;

    auto increment_elements = [](vector<int*>& v) {
        for (auto& i : v) { ++*i };
    };

    increment_elements(vector<int*>{&x, &y, &z});

    cout << x << ", " << y << ", " << z << endl;
}

Replacing

for (auto& i : v) { ++*i };

with

for (int& i : v) { ++i };

gives MSVC-2013

error C2440: 'initializing' : cannot convert from 'int *' to 'int &'.

Why does replacement with

for (auto& i : v) { ++i };

compile but without incrementing the ints, and what is it doing?

I have the same question regarding replacement with

for (int*& i : v) ++i;

which gives the same result.

2

There are 2 best solutions below

1
On BEST ANSWER

Given a container of pointers to ints, how can I increment the ints without using a dereference operator * within the loop body {}?

Uses references over pointers whenever you can. You can't make vector of reference type so instead you can use a std::reference_wrapper<int>.

std::vector<std::reference_wrapper<int>> v{x, y, z};

increment_elements should probably also take a range to stay in line with generic programming. Then use get() on the elements and increment them:

template<class Iter>
void increment_elements(Iter first, Iter last)
{
    for (; first != last; ++first->get(), ++first);
}

Then you can call it using begin() and end():

increment_elements(std::begin(v), std::end(v));

Or if you still want to take a vector as an argument, you can just iterate through and increment:

for (int& i : v) ++i;

and call it as:

increment_elements(v);

Why does replacement with [...] compile but without incrementing the ints, and what is it doing?

auto deduces the element type as int* so decltype(i) becomes int*& which does the same thing as your last example.

0
On

Your vector is vector<int *>, not vector<int>!

vector<int *> &v;
for (auto &i : v)
    ++(*i);

v is vector of int *. so, the type of i is int* &. Therefore, you should use ++(*i); to increase x, y and z.

for (int &i : v)
    ++i;

This is wrong. v is vector of int *, but you're trying to assign int * to int &.

for (auto &i : v)
    ++i;

This code is increase the pointers, not x, y, z. Since it's equal to

for (std::vector<int *>::iterator it = v.begin(); it != v.end(); ++it)
    ++(*it);