“在成员函数之外的封闭类的定义中需要默认成员初始值设定项” - 我的代码是不正确的?

时间:2017-10-21 18:36:33

标签: c++ c++11 language-lawyer inner-classes noexcept

struct foo
{
    struct bar {
        ~bar() {}                // no error w/o this line
    };
    bar *data = nullptr;         // no error w/o this line
    foo() noexcept = default;    // no error w/o this line
};

是的,我知道,还有另一个问题完全相同的标题,但有一个不同的问题(涉及noexcept 运算符并且没有嵌套类型)。解决方案建议在那里(用{/ 1>替换foo的构造函数)

    foo() noexcept {}

)改变了语义,这里没有必要:这里我们有一个更好的答案(因此问题不是重复的)。

编译器:Apple LLVM version 9.0.0 (clang-900.0.37),完整错误消息:

test.cc:44:5: error: default member initializer for 'data' needed within definition of enclosing class 'foo' outside of member functions
    foo() noexcept = default;
    ^
test.cc:41:10: note: default member initializer declared here
    bar* data = nullptr;
         ^

2 个答案:

答案 0 :(得分:3)

这是一个铿锵的错误。但是有一个简单的解决方法。

当一个特殊成员函数定义为默认值时,noexcept说明符仅用于检查编译器生成的默认特殊成员是noexcept[dcl.sft.dcl.def]

  

如果使用a声明显式默认的函数    noexcept说明符   这不会产生相同的   异常规范作为隐式声明(18.4),然后是

     

- 如果函数在其第一个声明中显式默认,则将其定义为已删除;

     

- 否则,该程序格式不正确。

因此,如果删除foo默认构造函数的noexcept sepcifier,则不会更改语义,foo仍然不会默认构造:

#include <type_traits>
struct foo
  {
  struct bar {
    ~bar() {}                // no error w/o this line
    };
  bar *data = nullptr;         // no error w/o this line
  foo()= default;    // foo is noexcept, weither the declarator contains noexcept or not
  };

static_assert(std::is_nothrow_default_constructible<foo>::value);

答案 1 :(得分:1)

可以通过默认嵌套类

的析构函数来解决问题
struct foo
{
    struct bar {
        ~bar() = default;        // this fixes it
    };
    bar *data = nullptr;         // no error w/o this line
    foo() noexcept = default;    // no error w/o this line
};

但是,我不清楚为什么/这是否是标准所要求的。