当基类的成员的析构函数具有非空的no指定符和主体时,在析构函数上使用C2694

弗朗索瓦·安德里厄

我遇到无法解释的编译器错误,也无法在线找到有关该错误的信息。我最近noexcept在包装器类的析构函数中添加了一个说明符,现在大量从使用该包装器的类继承的类无法编译。我已经在GCC 4.9上尝试过了,没有编译器错误。

我正在使用Visual Studio Professional 2015版本14.0.25431.01更新3

请考虑下面的重现此问题的最小代码:

#include <type_traits>

template<class T>
struct member
{
    ~member() noexcept(std::is_nothrow_destructible<T>::value) {};
};

struct parent
{ 
    virtual ~parent() noexcept = default;
};


struct derived : public parent
{
    member<int> x;
};

该代码段产生以下错误消息:

1>c:\users\fandrieux\workspace\tmp\dtor_noexcept\main.cpp(19): error C2694: 'derived::~derived(void) noexcept(<expr>)': overriding virtual function has less restrictive exception specification than base class virtual member function 'parent::~parent(void) noexcept'
1>  c:\users\fandrieux\workspace\tmp\dtor_noexcept\main.cpp(19): note: compiler has generated 'derived::~derived' here
1>  c:\users\fandrieux\workspace\tmp\dtor_noexcept\main.cpp(12): note: see declaration of 'parent::~parent'

我发现有趣的是,如果您用= default或使用noexcept替换成员的析构函数主体,则编译器错误会消失noexcept(true)

// None of these produce compiler errors
virtual ~member() noexcept(std::is_nothrow_destructible<T>::value) = default;
virtual ~member() noexcept(true) {}
virtual ~member() noexcept {}

我知道它的析构函数不会抛出。偏执狂和怀疑论者(像我一样)可以添加以下静态断言,并对其进行检查:

static_assert(std::is_nothrow_destructible<T>::value, "Might throw!");

根据MSDN,这表明动态异常说明符不足。这在这里如何适用?noexcept([boolean expression])等于noexcept(true)等于noexcept(false)吗?为什么这种变化取决于功能体的存在?在派生对象上添加显式的noexcept析构函数可以避免编译器错误,但这似乎是不必要的解决方法。实际上,当您考虑必须更新每个派生类时,这也是一个负担。

八进制

这看起来像是编译器错误。如果我们添加以下类:

struct dtor_throws
{
    ~dtor_throws() noexcept(false) {}
};

从而改变定义derived

struct derived : public parent
{
    member<dtor_throws> x;
};

然后GCC和Clang都抱怨的异常规范~derived比宽松~parent

在原始示例中,MSVC似乎没有表达式嵌入的noexcept类型~parent,而只是将noexcept用户定义的类模板的析构函数的所有复合规范视为比宽松noexcept(true)

MSVC 2017 RC也受到影响。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

“ = default”析构函数和空析构函数之间有什么区别?

C ++ Qt基类虚拟析构函数

在成员函数上启动线程时发生不希望的析构函数调用

noexcept函数返回具有抛出析构函数的类

零与基类析构函数的规则

虚拟析构函数= default与空主体的虚拟析构函数之间有什么区别吗?

如果类具有析构函数/删除[],则成员运算符new []的参数“ size”增加

具有虚拟析构函数的基类的子类中的默认析构函数

是否可以实例化具有删除的构造函数和析构函数的非聚合类?

具有外部无法解析的C ++虚拟析构函数

非静态类成员即使没有析构函数也会被销毁吗?

模板类的析构函数

当基类具有受保护的析构函数时,创建unique_ptr <Base>

C ++中的原始类型是否具有析构函数?

具有shared_ptr的成员的C ++析构函数顺序

具有unique_ptr成员和自定义析构函数的对象的向量

C ++:具有成员的抽象类中的纯虚拟析构函数

C ++类变量析构函数

C ++分配和析构函数

C ++派生类和虚拟析构函数

析构函数限制-从析构函数访问托管成员

没有析构函数的C ++函数

使用析构函数时清除成员变量

返回类析构函数

C++ 可以使析构函数不调用类成员的析构函数和基类的析构函数吗?

如果“所有者”,C++ 类析构函数删除成员?

具有私有构造函数和析构函数的类对象的向量?

类和成员析构函数调用两次

C ++:使用仅具有属性的继承结构时需要实现虚拟析构函数吗?