警告 C5246: 子对象的初始化应该用大括号括起来

warning C5246: the initialization of a subobject should be wrapped in braces

最新的 Visual Studio 2019 使用 /Wall 命令行开关(启用所有警告)编译以下代码:

struct A{};

void f( const std::array<A, 2> & ) {}

int main() {
    A x, y;
    f( { x, y } );
}

打印警告:

warning C5246: 'std::array<A,2>::_Elems': the initialization of a subobject should be wrapped in braces

但是 GCC 和 Clang 都接受带有最迂腐错误检查的代码,演示:https://gcc.godbolt.org/z/Ps6K6jK1G

确实,所有编译器都接受调用 f( { { x, y } } );

MSVC 建议使用没有额外大括号的更简单形式是否正确?

我相信 Clang 和 GCC 现在默认抑制该错误,因此警告不会透露实施细节。话虽如此,VS 过去不会给我使用 C++11 的错误,而 Clang 会(所以他们似乎已经解决了这个问题)。所有文档都表明双花括号是最合适的,添加它们以匹配行业标准代码实践可能是有意义的。

Visual Studio 2019 具有 CWG defect #1270 并提供旧的初始化行为。

std::array 定义为包含另一个聚合的聚合。

C++ 17 标准(11.6.1 聚合)

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.

您可以将 std::array<A, 2> 想象成

struct Array {
    A sub[2];
};

根据引用 Array a {{x, y}} 是正确的,但已过时,内部大括号是封闭数组的 aggregate initialization

有用的线程Why is the C++ initializer_list behavior for std::vector and std::array different?