非平凡析构函数使得类非可概括地构造 [英] Non-trivial destructor make class non-trivially-constructible

查看:309
本文介绍了非平凡析构函数使得类非可概括地构造的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下代码:

#include <type_traits>

struct T {};

static_assert(std::is_trivially_destructible< T >{});
static_assert(std::is_trivially_default_constructible< T >{});

struct N { ~N() { ; } };

static_assert(!std::is_trivially_destructible< N >{});
static_assert(!std::is_trivially_default_constructible< N >{});

使用 clang 3.7.0 实例。但总结标准


如果以下所有条件都为真,则类T的默认构造函数是微不足道的(即不执行任何操作):

The default constructor for class T is trivial (i.e. performs no action) if all of the following is true:


  • 构造函数不是用户提供的(即隐式定义或默认)。

  • T没有虚拟成员函数

  • T没有虚拟基类

  • T没有具有默认初始值设置的非静态成员。
    (自C ++ 11开始)

  • 每个T的直接基础都有一个琐碎的默认构造函数

  • 类的每个非静态成员type有一个琐碎的默认构造函数

  • The constructor is not user-provided (i.e., is implicitly-defined or defaulted)
  • T has no virtual member functions
  • T has no virtual base classes
  • T has no non-static members with default initializers. (since C++11)
  • Every direct base of T has a trivial default constructor
  • Every non-static member of class type has a trivial default constructor

正如我看到的, 。

我错过了什么?是 clang 错误吗?

I missed something? Is it clang bug?

找到了一个解决方法: static_assert(__ has_trivial_constructor(N)); 内置类型trait。在 clang gcc MSVC code>

I found a workaround: is static_assert(__has_trivial_constructor( N )); built-in type trait. There is support in clang, gcc and MSVC.

对于 is_noexcept_constructible 系列类型traits 也有解决方法

For is_noexcept_constructible family of type traits there is workaround too.

推荐答案

此问题在 LWG问题2116中有所说明:std :: swap noexcept(what ?),我们可以从的cppreference部分看到这一点std :: is_trivially_default_constructible

This issue is covered in LWG issue 2116: std::swap noexcept(what?), we can see this from the cppreference section for std::is_trivially_default_constructible:


在许多实现中,is_nothrow_default_constructible还检查析构函数是否抛出,因为它实际上不存在51452 LWG问题2116

In many implementations, is_nothrow_default_constructible also checks if the destructor throws because it is effectively noexept(T()): GCC bug 51452 LWG issue 2116

其实只是谈论 is_nothrow_default_constructible ,但如果我们读

which deceptively only talks about is_nothrow_default_constructible but if we read the issue in detail we see it also applies here as well.

也许如果我们遵循 gcc错误报告:[DR 2116] has_nothrow _。*构造函数错误首先引用,说:

Perhaps is is easier if we follow the gcc bug report: [DR 2116] has_nothrow_.*constructor bugs referenced first which says:


检测不可构造性的特征是错误的,因为它们受到对象是否具有未删除dtor的影响;在noexcept(...)运算符的完整表达式的求值结束时调用销毁。他们都使用构造临时内部noexcept的模式,而他们应该使用placement new

The traits that detect nothrow constructibility are buggy because they are influenced by whether the object has a nothrow dtor; destruction is invoked at the end of evaluation of the full expression in the noexcept( ... ) operator. They all use the pattern of constructing a temporary inside noexcept, whereas they should be using placement new

这明确说明什么是真正地暗示在LWG问题中,最终说:

this explicitly says what is only really alluded to in the LWG issue which eventually says:


is_nothrow_constructible在 is_constructible术语中定义,is_constructible是通过查看假设变量并询问变量定义是否知道不抛出异常。问题声称,这也检查类型的析构函数,给定上下文,因此将返回假如果析构函数可能抛出。如果构造函数是noexcept(true)和析构函数是noexcept(false),至少有一个实现(Howard's)返回false。所以这不是一个紧张的解释。问题是要求根据位置new,而不是临时对象来定义它,以使它更清楚is_nothrow_constructible看看noexcept状态只有构造函数,而不是析构函数。

is_nothrow_constructible is defined in terms of is_constructible, which is defined by looking at a hypothetical variable and asking whether the variable definition is known not to throw exceptions. The issue claims that this also examines the type's destructor, given the context, and thus will return false if the destructor can potentially throw. At least one implementation (Howard's) does return false if the constructor is noexcept(true) and the destructor is noexcept(false). So that's not a strained interpretation. The issue is asking for this to be defined in terms of placement new, instead of in terms of a temporary object, to make it clearer that is_nothrow_constructible looks at the noexcept status of only the constructor, and not the destructor.


b b std :: is_trivially_default_constructible http://en.cppreference.com/w/cpp/types/is_constructible =nofollow> std :: is_trivially_constructible 与 is_constructible 但有进一步的限制:

which also effects std::is_trivially_default_constructible which relies on std::is_trivially_constructible which does the same as is_constructible but has the further restriction that:


但是变量定义不调用任何不重要的操作

but the variable definition does not call any operation that is not trivial

这篇关于非平凡析构函数使得类非可概括地构造的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆