12

In C++11, is it possible to write the following

int ns[] = { 1, 5, 6, 2, 9 };
for (int n : ns) {
   ...
}

as something like this

for (int n : { 1, 5, 6, 2, 9 }) { // VC++11 rejects this form
   ...
}
Thomas Eding
  • 35,312
  • 13
  • 75
  • 106

2 Answers2

19

tl;dr: Upgrade your compiler for great success.


Yeah, it's valid.

The definition of ranged-for in [C++11: 6.5.4/1] gives us two variants of syntax for this construct. One takes an expression on the right-hand-side of the :, and the other takes a braced-init-list.

Your braced-init-list deduces (through auto) to a std::initializer_list, which is handy because these things may be iterated over.

[..] for a range-based for statement of the form

for ( for-range-declaration : braced-init-list ) statement

let range-init be equivalent to the braced-init-list. In each case, a range-based for statement is equivalent to

{
   auto && __range = range-init;
   for ( auto __begin = begin-expr,
              __end = end-expr;
        __begin != __end;
        ++__begin ) {
      for-range-declaration = *__begin;
      statement
   }
}

[..]

So, you are basically saying:

auto ns = { 1, 5, 6, 2, 9 };
for (int n : ns) {
   // ...
}

(I haven't bothered with the universal reference here.)

which in turn is more-or-less equivalent to:

std::initializer_list<int> ns = { 1, 5, 6, 2, 9 };
for (int n : ns) {
   // ...
}

Now, GCC 4.8 supports this but, since "Visual Studio 11" is in fact Visual Studio 2012, you'll need to upgrade in order to catch up: initialiser lists were not supported at all until Visual Studio 2013.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Since when do you quote a compiler in the wild as the authoritative source? I mean, I **know** it's correct, but I'm expecting a standards quote/link to existing answer from you :) – sehe Feb 10 '14 at 22:55
6

It is possible to use this construction with an initializer list. Simply it seems the MS VC++ you are using does not support it.

Here is an example

#include <iostream>
#include <initializer_list>

int main() 
{
    for (int n : { 1, 5, 6, 2, 9 }) std::cout << n << ' ';
    std::cout << std::endl;

    return 0;
}

You have to include header <initializer_list> because the initializer list in the for statement is converted to std::initializer_list<int>

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335