【问题标题】:warning C5246: the initialization of a subobject should be wrapped in braces警告 C5246:子对象的初始化应该用大括号括起来
【发布时间】:2022-01-04 16:14:12
【问题描述】:

最新的 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 是否建议它支持更简单的形式而无需额外的大括号?

【问题讨论】:

    标签: c++ visual-studio language-lawyer compiler-warnings


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

      C++ 17 标准(11.6.1 聚合)

      12 大括号可以在初始化列表中被省略,如下所示。如果初始化器列表以左大括号开头,则随后的初始化器子句的逗号分隔列表初始化子聚合的元素;初始化子句多于元素是错误的。但是,如果子聚合的初始化器列表不以左大括号开头,则仅从列表中获取足够的初始化器子句来初始化子聚合的元素;剩下的任何初始化子句都被留下来初始化聚合的下一个元素,当前子聚合是其中的一个元素。

      你可以把std::array&lt;A, 2&gt;想象成

      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?

      【讨论】:

        猜你喜欢
        • 2012-11-21
        • 2016-12-11
        • 1970-01-01
        • 1970-01-01
        • 2013-08-23
        • 2021-07-18
        • 1970-01-01
        • 1970-01-01
        • 2022-01-07
        相关资源
        最近更新 更多