为什么默认构造性对于使用 NSDMI 的内部结构会表现得很奇怪?

ein*_*ica 5 c++ default-constructor c++11 nsdmi

考虑以下代码:

#include <type_traits>

struct outer {
    struct inner {
        unsigned int x = 0;
    };
//    static_assert(std::is_default_constructible<inner>::value,
//          "not default ctorable - inside");
};

static_assert(std::is_default_constructible<outer::inner>::value,
    "not default ctorable - outside");
Run Code Online (Sandbox Code Playgroud)

编译得很好。但是 - 如果我取消注释内部的静态断言outer- 两个断言都会因 clang++ 和 gcc++ 失败。为什么他们不能都通过?

笔记:

  • inner事实上,在第一个静态断言的点上,这个类是完整的。断言不会因不完整而失败(失败会产生关于不完整的特定错误消息)。

  • 与相关的为什么我的类不可默认构造不同?,这里 - 没有模板,所以没有定义前的实例化。

  • 如果删除 的初始化程序x并启用断言,则代码会编译。(这也不同于相关问题。)

  • 这个:

    #include <type_traits>
    
    struct outer {
         struct inner {
             unsigned int x = 0;
         };
    
         inner get_an_inner() { 
             static_assert(std::is_default_constructible<outer::inner>::value,
                 "not default ctorable - outside");
             return inner{}; 
         }
    };
    
    Run Code Online (Sandbox Code Playgroud)

    编译!

  • 如果我们添加一个显式的默认构造函数,constexpr inner() {}- 程序会编译。

  • 有一个LLVM 错误报告关于基本相同的事情,但不仅仅是叮当声,错误报告还没有得到任何评论。

更新:

  • 已提交GCC 错误 102199(针对 libstdc++)。
  • 已评论 LLVM 错误,让我们看看那里会发生什么。

Dav*_*ing 5

成员类的完整性状态很复杂。因为它们的成员函数被允许对周围的类范围进行前向查找,所以在处理包含类的(其余部分)时,这些成员函数被视为尚未定义,尽管最基本的完整性概念显然得到满足

struct A {
  struct B {};
  B b;          // OK
};
Run Code Online (Sandbox Code Playgroud)

在这个一般领域有各种未解决的问题例如 CWG2335CWG1360

  • @einpoklum:我不是说它很复杂,而且这里存在语言缺陷吗? (3认同)