The latest Visual Studio 2019 compiling the following code with /Wall command-line switch (which enables all warnings):
struct A{};
void f( const std::array<A, 2> & ) {}
int main() {
A x, y;
f( { x, y } );
}
prints the warning:
warning C5246: 'std::array<A,2>::_Elems': the initialization of a subobject should be wrapped in braces
however both GCC and Clang accepts the code with the most pedantic error checking, demo: https://gcc.godbolt.org/z/Ps6K6jK1G
Indeed, all compilers accept the call f( { { x, y } } );
Is MSVC right in suggesting it in favor of the simpler form without extra braces?
Visual Studio 2019 has the CWG defect #1270 and offers the old initialization behaviour.
std::array is defined as an aggregate that contains another aggregate.
C++ 17 Standard (11.6.1 Aggregates)
12 Braces can be elided in an initializer-list as follows. If the initializer-list begins with a left brace, then the succeeding comma-separated list of initializer-clauses initializes the elements of a subaggregate; it is erroneous for there to be more initializer-clauses than elements. If, however, the initializer-list for a subaggregate does not begin with a left brace, then only enough initializer-clauses from the list are taken to initialize the elements of the subaggregate; any remaining initializer-clauses are left to initialize the next element of the aggregate of which the current subaggregate is an element.
You may imagine std::array<A, 2> as
struct Array {
A sub[2];
};
According to the quote Array a {{x, y}} is correct, but obsolete, the inner braces is aggregate initialization of the enclosed array.
Useful thread Why is the C++ initializer_list behavior for std::vector and std::array different?.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With