gpt4 book ai didi

c++ - 为什么这段代码会出现 "exception spec is more lax than base"错误?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:34:29 61 4
gpt4 key购买 nike

尝试使用 Xcode 6.1 中的 clang 版本(基于 LLVM 3.5svn 的 clang-600.0.54)编译以下代码,使用 -std=c++11-stdlib =libc++ 给我一些我不太明白的错误。

#include <functional>

struct Impl
{
typedef std::function<void ()> L;
L l;
int i;
};

struct Hndl
{
Impl* impl;
Hndl(Impl* i): impl(i) {}
~Hndl() noexcept(false) {}
};

int main(int argc, char * argv[]) {
Hndl h(new Impl());
h.impl->l = [=]
{
h.impl->i = 42;
};
return 0;
}

结果:

In file included from t.cpp:1:
/Applications/Xcode-6.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/functional:1293:52: error: exception specification of overriding
function is more lax than base version
template<class _FD, class _Alloc, class _FB> class __func;
^
/Applications/Xcode-6.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/functional:1593:13: note: in instantiation of template class
'std::__1::__function::__func<<lambda at t.cpp:20:14>, std::__1::allocator<<lambda at t.cpp:20:14> >, void ()>' requested here
if (sizeof(_FF) <= sizeof(__buf_) && is_nothrow_copy_constructible<_Fp>::value)
^
/Applications/Xcode-6.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/functional:1697:5: note: in instantiation of function template
specialization 'std::__1::function<void ()>::function<<lambda at t.cpp:20:14> >' requested here
function(_VSTD::forward<_Fp>(__f)).swap(*this);
^
t.cpp:20:12: note: in instantiation of function template specialization 'std::__1::function<void ()>::operator=<<lambda at t.cpp:20:14> >' requested here
h.impl->l = [=]
^
/Applications/Xcode-6.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/functional:1281:39: note: overridden virtual function is here
_LIBCPP_INLINE_VISIBILITY virtual ~__base() {}
^
1 error generated.

看起来好像 Impl::L::~L() 以某种方式继承了 Hndl::~Hndl() noexcept(false),但我不知道为什么。有趣的是,如果我在 lambda 中注释掉对 h.impl->i 的赋值,则可以编译相同的代码。如果我从 Hndl::~Hndl() 中删除 noexcept(false) 规范,也会编译,但我需要它(解释原因会有点长,但我做)。如果 lambda 通过 ref 捕获,也会编译,但这里的重点是能够复制共享实现的句柄。将 noexcept(true) 添加到 Impl::~Impl() 没有帮助。

ideone.com 的 c++11 编译器很乐意按原样编译它。

谁能给我解释一下这里发生了什么?

最佳答案

lambda 捕获 h,它有一个潜在抛出的析构函数,所以 lambda 的闭包类型也有一个潜在抛出的析构函数。

考虑到这一点,您可以将问题简化为:

#include <functional>

struct F
{
void operator()() { }

~F() noexcept(false) {}
};

int main() {
std::function<void ()> f = F{};
}

似乎 libc++ 中的 std::function 无法存储没有 nothrow 析构函数的可调用类型,这看起来像 libc++ 中的错误。

从错误消息看来,修复可能就像向 __func 析构函数添加显式 noexcept 一样简单,但我不熟悉实现所以可能没那么容易。

除了用 noexcept 析构函数将你的 Hndl 类型包装成另一种类型外,我没有看到任何明显的解决方法,所以在 lambda 中捕获它不会使 lambda 具有一个 noexcept(false) 析构函数。我试过这样的东西,但 libc++ 似乎在 shared_ptr 中有类似的问题:

    std::function<void ()> f = std::bind(&Hndl::operator(), std::make_shared<Hndl>());

关于c++ - 为什么这段代码会出现 "exception spec is more lax than base"错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26673204/

61 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com