Sim*_*mon 6 c++ type-traits language-lawyer c++11
以下代码无法使用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在第二个语句中没有调用析构函数.
我们可以看到std::is_nothrow_move_constructible是根据is_\xc2\xadnothrow_\xc2\xadconstructible_\xc2\xadv定义的。因此,这最终被LWG 问题 2116: is_nothrow_constructible and destructors\n覆盖,该问题尚未解决,因此这不是一个错误,除非该问题的解决方式与当前实现的行为方式不同。
它以以下讨论开始:
\n\n\n\n\nIMO 如果我们根据变量声明指定 is_[nothrow_]constructible ,而其有效性需要可破坏性,那么这显然是我们规范中的一个错误,并且未能实现实际的原始意图。该规范应该是新的布局。
\n\nDaniel:在制定规范时,这是有意为之的,并且解决方案并不是通过删除 is_constructible 的破坏语义来完成的。
\n\nis_constructible 的设计也受到之前显式包含破坏语义的可构造概念的影响,因为在库的概念化过程中,它简化了库中的约束,因为您不需要添加 Destructible每时每刻。在 C++03 中,它经常是隐含的,但从未说出来。
\n\n纯构造语义也被认为是有用的,因此 HasConstructor 也确实存在,并且肯定也可以作为特征使用。
\n\n另一个经常被忽视的例子:这也会影响包装器类型,例如可能包含多个类型的对、元组、数组:如果您认为 T1 有一个已删除的析构函数,而 T2 有一个析构函数,那么这很容易理解可能抛出的构造函数:显然,\n 编译器可能需要在 std::pair 的\n 构造函数中使用 T1 的析构函数,以确保满足核心语言\n 要求(所有先前完全构造的子对象\n必须销毁)。
\n\n核心语言也在 [class.copy] p11 中尊重了这一事实:
\n\n\n\n\n\n
如果 X 具有: \n [\xe2\x80\xa6]
\n \xe2\x80\x94 ,则类 X 的默认复制/移动构造函数被定义为已删除 (9.4.3 [dcl.fct.def.delete])任何直接或虚拟基类或具有析构函数的类型的非静态数据成员,该析构函数已从默认构造函数中删除或无法访问
\n [\xe2\x80\xa6]Dave:这尤其是关于 is_nothro_constructible 的。事实上,它因没有 noexcept dtor 而被挫败,这是一个缺陷。
\n
它的结论是:
\n\n\n\n\n维尔希望“一个进化小组”来研究这个问题。
\n
从这个 gcc bug 报告来看,至少 gcc 将等待问题得到解决。
\n\n另请参阅Non-trivial destructor make class non-trivially-constructible,其中涵盖了对相关问题的一些其他引用。另请注意此问题的 clang 错误。
\n| 归档时间: | 
 | 
| 查看次数: | 519 次 | 
| 最近记录: |