【问题标题】:Does std::is_nothrow_move_constructible require a noexcept destructor?std::is_nothrow_move_constructible 是否需要 noexcept 析构函数?
【发布时间】:2018-06-19 13:02:24
【问题描述】:

以下代码无法使用 Visual Studio 2017 (15.5)、gcc 6.4.0 和 clang 4.0.1 编译,即静态断言失败:

struct Type
{
  Type(Type&&) noexcept {}

  ~Type() noexcept(false) {}
};

static_assert(std::is_nothrow_move_constructible<Type>::value, "Type should be nothrow-move-constructible");
static_assert(std::is_nothrow_constructible<Type, Type&&>::value, "Type should be nothrow-constructible from Type&&");

C++ 标准是否正确? std::is_nothrow_move_constructible 是否需要 noexcept 析构函数?为什么?

如果我这样使用:

Type a;
Type b(std::move(a));  

a 的析构函数在第二条语句中没有被调用。

【问题讨论】:

  • 仅供参考:跟随链(以 en.cppreference.com/w/cpp/types/is_move_constructible 开头)std::is_nothrow_move_constructible -> std::is_nothrow_constructible 您可以在此处看到此注释:“在许多实现中,is_nothrow_constructible 还检查析构函数是否抛出...” en.cppreference.com/w/cpp/types/is_constructible
  • @RichardCritten 感谢您的提示!由于此显式引用“许多实现”,因此听起来此行为不符合标准。如果标准将此作为实现的选择,我会感到惊讶。

标签: c++ c++11 language-lawyer typetraits


【解决方案1】:

我们可以看到std::is_nothrow_move_constructible 是根据is_­nothrow_­constructible_­v 定义的。所以这最终被 LWG issue 2116: is_nothrow_constructible and destructors 覆盖,但没有解决,所以这不是一个错误,除非问题得到解决的方式与当前实现的行为方式不同。

它以以下讨论开始:

如果我们根据变量指定 is_[nothrow_] 可构造,则 IMO 其有效性要求可破坏性的声明,显然是 我们的规范中的错误和未能实现实际的原始 意图。规范应该是关于placement-new的。

Daniel:在制定规范时,这是预期的,而 解决方案不是通过删除破坏语义来完成的 is_constructible。

is_constructible 的设计也受到了之前的影响 明确包含破坏语义的可构造概念, 因为在图书馆的概念化过程中,结果证明 简化库中的约束,因为您不需要 一直添加 Destructible。它经常被暗示但从未说过 在 C++03 中。

纯构造语义也被认为是有用的,所以 HasConstructor 也确实存在,并且肯定会作为 trait 有用 嗯。

另一个经常被忽视的例子:这也会影响 wrapper 可能包含多个类型的对、元组、数组等类型 type:这很容易理解,如果您认为 T1 有一个已删除的 析构函数和 T2 有一个可能抛出的构造函数:显然 编译器可能需要在 std::pair 的构造函数以确保核心语言 满足要求(所有先前完全构造的子对象 必须销毁)。

核心语言在 [class.copy] p11 中也尊重这一事实:

如果 X 具有以下属性,则类 X 的默认复制/移动构造函数被定义为已删除 (9.4.3 [dcl.fct.def.delete]):
[…]
— 任何直接或虚拟基类或具有析构函数的类型的非静态数据成员,该析构函数已从 默认构造函数,
[…]

Dave:这尤其是关于 is_nothrow_constructible。事实 由于没有 noexcept dtor 而被挫败是一个缺陷。

结尾是:

Ville 希望“一个进化小组”来研究这个问题。

来自this gcc bug report,至少 gcc 将等待问题得到解决。

另请参阅Non-trivial destructor make class non-trivially-constructible,其中涵盖了对相关问题的一些其他参考。还要注意clang bug for this

【讨论】:

    猜你喜欢
    • 2017-06-30
    • 2018-10-06
    • 1970-01-01
    • 1970-01-01
    • 2013-03-21
    • 1970-01-01
    • 2017-02-26
    • 1970-01-01
    相关资源
    最近更新 更多