1

This is question is out of curiosity, not necessity. One way I have found C++11's range based for loop useful is for iterating over discrete objects:

#include <iostream>
#include <functional>

int main()
{
    int a = 1;
    int b = 2;
    int c = 3;

    // handy:
    for (const int& n : {a, b, c}) {
        std::cout << n << '\n';
    }

I would like to be able to use the same loop style to modify non-const references too, but I believe it is not allowed by the standard (see Why are arrays of references illegal?):

    // would be handy but not allowed:
    // for (int& n : {a, b, c}) {
    //     n = 0;
    // }

I thought of two workarounds but these seem like they could incur some minor additional cost and they just don't look as clean:

    // meh:
    for (int* n : {&a, &b, &c}) {
        *n = 0;
    }

    // meh:
    using intRef = std::reference_wrapper<int>;
    for (int& n : {intRef (a), intRef (b), intRef (c)}) {
        n = 0;
    }
}

So the question is, is there a cleaner or better way? There may be no answer to this but I'm always impressed with the clever ideas people have on stackoverflow so I thought I would ask.

atb
  • 1,412
  • 1
  • 14
  • 30

2 Answers2

2

Instead of constructing a reference_wrapper yourself you could use std::ref, that's as far as you can get:

using std::ref;
for (int& n : {ref(a), ref(b), ref(c)}) {
    n = 0;
}
Hatted Rooster
  • 35,759
  • 6
  • 62
  • 122
2

Picking up @Sombrero Chicken's idea, here is an approach with less typing:

template <class ...Args> constexpr auto ref(Args&&... args)
{
   using First = std::tuple_element_t<0, std::tuple<Args...>>;
   using WrappedFirst = std::reference_wrapper<std::remove_reference_t<First>>;
   constexpr auto n = sizeof...(Args);

   return std::array<WrappedFirst, n>{std::ref(args)...};
}

which can be used via

for (int& n : ref(a, b, c))
    n = 0;
lubgr
  • 37,368
  • 3
  • 66
  • 117