imr*_*mre 5 c++ lambda noexcept c++11 libc++
尝试使用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;
}
Run Code Online (Sandbox Code Playgroud)
结果:
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.
Run Code Online (Sandbox Code Playgroud)
看起来好像Impl::L::~L()在某种程度上继承noexcept(false)的Hndl::~Hndl(),但我不知道为什么.有趣的是,如果我将赋值注释到h.impl->ilambda内部,则编译相同的代码.如果我noexcept(false)从中删除规范Hndl::~Hndl()也会编译,但我需要(解释原因有点长,但我确实如此).如果lambda通过ref捕获,也会编译,但这里的重点是能够复制共享实现的句柄.添加noexcept(true)到Impl::~Impl()于事无补.
ideone.com的c ++ 11编译器很乐意按原样编译它.
谁能解释一下这里发生了什么?
lambda capturesh具有潜在抛出的析构函数,因此 lambda 的闭包类型也具有潜在抛出的析构函数。
考虑到这一点,您可以将问题简化为:
#include <functional>
struct F
{
void operator()() { }
~F() noexcept(false) {}
};
int main() {
std::function<void ()> f = F{};
}
Run Code Online (Sandbox Code Playgroud)
似乎std::functionlibc++ 中的 不能在没有 nothrow 析构函数的情况下存储可调用类型,这看起来像是 libc++ 中的一个错误。
从错误消息看来,修复可能就像noexcept向__func析构函数添加显式一样简单,但我不熟悉实现,所以可能没那么容易。
Hndl除了使用析构函数将您的类型包装在另一种类型中之外,我没有看到任何明显的解决方法noexcept,因此在 lambda 中捕获它并不会使 lambda 具有noexcept(false)析构函数。我尝试过类似的方法,但 libc++ 似乎也有类似的问题shared_ptr:
std::function<void ()> f = std::bind(&Hndl::operator(), std::make_shared<Hndl>());
Run Code Online (Sandbox Code Playgroud)