【发布时间】:2017-05-15 02:46:23
【问题描述】:
我遇到了无法解释的编译器错误,也无法在网上找到相关信息。我最近在包装类的析构函数中添加了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;
};
sn-p 产生以下错误信息:
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!");
According to MSDN 表示动态异常说明符不足。这在这里如何应用? noexcept([boolean expression]) 不等于noexcept(true) 或noexcept(false) 吗?为什么这会根据函数体的存在而改变?向派生添加显式 noexcept 析构函数可以避免编译器错误,但这感觉像是一种不必要的解决方法。实际上,当您考虑到每个派生类都必须更新时,这也是一个相当大的负担。
【问题讨论】:
-
让赞成票自己说话,但这是一个很好的问题。谢谢,祝你好运
-
Fwiw,除了 gcc 4.9,它还在语言级别 c++14 下通过了 clang 3.8,没有任何问题。
-
看起来像一个编译器错误。
-
我确信这个问题可以得到改进 - 但我认为我们最好担心最后 1000 个首先提出的问题中的 999 个较差的问题。
标签: c++ visual-studio visual-studio-2015