首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >当基类的成员析构函数具有非空的noexcept说明符和正文时,析构函数上的C2694

当基类的成员析构函数具有非空的noexcept说明符和正文时,析构函数上的C2694
EN

Stack Overflow用户
提问于 2016-12-31 04:32:25
回答 1查看 1.2K关注 0票数 17

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

我使用的是Visual Studio Professional 2015版本14.0.25431.01 Update 3

考虑以下重现问题的最小代码:

代码语言:javascript
复制
#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;
};

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

代码语言:javascript
复制
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替换成员的析构函数体,或者使用noexceptnoexcept(true),编译器错误就会消失:

代码语言:javascript
复制
// None of these produce compiler errors
virtual ~member() noexcept(std::is_nothrow_destructible<T>::value) = default;
virtual ~member() noexcept(true) {}
virtual ~member() noexcept {}

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

代码语言:javascript
复制
static_assert(std::is_nothrow_destructible<T>::value, "Might throw!");

According to MSDN它表示动态异常说明符不足。这在这里是如何应用的?noexcept([boolean expression])不是等同于noexcept(true)noexcept(false)吗?为什么这种变化依赖于函数体的存在?向派生函数添加显式的非异常析构函数可以避免编译器错误,但这感觉像是一种不必要的变通方法。在实践中,当你考虑到每个派生类都必须更新时,这也是一个相当大的负担。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-12-31 05:51:00

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

代码语言:javascript
复制
struct dtor_throws
{
    ~dtor_throws() noexcept(false) {}
};

并因此更改derived的定义:

代码语言:javascript
复制
struct derived : public parent
{
    member<dtor_throws> x;
};

然后,GCC和克朗都抱怨说,~derived的异常规范比~parent宽松。

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

MSVC 2017 RC也受到影响。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41402348

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档