-2

In a naive attempt to execute the same manipulation on several variables of the same type, I tried the following syntax (with C++20):

int var1, var2, var3;
for(auto& x : {var1, var2, var3})
  x += 1;

Unfortunately this does not compile as the type of x is const int& rather than int& which I hoped for. I could work around using

int var1, var2, var3;
for(auto px : {&var1, &var2, &var3})
  (*px) += 1;

but that does not seem very pretty. Is there a convenient way that I overlooked? I'm looking for something similarly easy to type and read as the first snippet, where the body of the for loop could just use an l-value reference.

Filip Konvička
  • 151
  • 1
  • 7
  • 4
    No, `x` is not `const` (otherwise compiler would give you an error). But the values in your initialiser list are copies of the original variables. – Yksisarvinen Aug 18 '23 at 13:07
  • @Yksisarvinen thanks. I admit that I tried `{std::ref(var1), std::ref(var2), std::ref(var3)}`, and this seems to have compiled for operations like `+=` but not `=` (assignment), which left me disappointed. – Filip Konvička Aug 18 '23 at 13:10
  • 3
    `std::tie` combined with `std::apply`? – 康桓瑋 Aug 18 '23 at 13:10
  • 3
    The question would be - if the values are all modified the same way, why are they not in `std::array`? – Yksisarvinen Aug 18 '23 at 13:13
  • 1
    The constness error given by the compiler is not about `x` but about the values in the initializer_list which are not mutable (you try to bind an `int&` to a `const int`). But anyway, since the values are copies of the original one, it would not work even if it compiled. – Fareanor Aug 18 '23 at 13:14
  • @Yksisarvinen because of code readability. In this particular case the variables actually reside in a `tuple`, then they are structure-bound using `auto& [var1, var2, var3] = var_tuple;`. Since the tuple storage type does not really matter to me, I tried changing that to `std::array` and then I can `for(auto& x : var_array)` without issues. Thanks! I still do not completely understand why the initializer list copies the values; I thought it was a lightweight data structure that references the "inputs". – Filip Konvička Aug 18 '23 at 13:19
  • Might be relevant: https://stackoverflow.com/questions/76876024/base-class-initializer-list-in-for-loop. – wohlstad Aug 18 '23 at 13:21
  • @康桓瑋 Thanks, but this is far less elegant to my eyes than a for loop. I do love lambdas, but sometimes they seem to make the code harder to read. – Filip Konvička Aug 18 '23 at 13:22
  • @Filip Konvička "*In this particular case the variables actually reside in a `tuple`*" Then you can directly use `std::apply` to operate [elements one by one](https://godbolt.org/z/vz9q894z6). – 康桓瑋 Aug 18 '23 at 13:24
  • @康桓瑋 Cool, thanks. I'm just afraid that too few of the people on the team would be able/happy to read this code. `for` is just a lot more understandable :) – Filip Konvička Aug 18 '23 at 13:27
  • @Yksisarvinen, @Fareanor, thanks for your explanation. It seems that in my particular case I can use the `std::array` approach. Regarding the original question, it seems that since the initializer list (contrary to my previous understanding) copies the values, it did not make sense to attempt to take l-value references to the members of that list, which would not refer to the original variables anyway. I'll be happy to accept a formulation of this fact as an answer. Thanks again. – Filip Konvička Aug 18 '23 at 13:30
  • 1
    For only 3 variables, `++var1; ++var2; ++var3;` is simple. – Jarod42 Aug 18 '23 at 13:56
  • @Jarod42 sure, but this was just an example. My real use case is about 10 lines worth of code with some if's. In my eyes, not enough to bother with a lambda, but too much to copy & paste. As I said I wondered if I was or wasn't close to being able to use the for loop. As it turned out, having the variables in an array is sufficient for this. But the original question related to the initializer list. – Filip Konvička Aug 18 '23 at 14:56
  • In my eyes, 10 lines is too mamy for lambda, so dedicated function ;-) – Jarod42 Aug 18 '23 at 16:11

0 Answers0