叮当如何检测无例外性?

How does clang detect noexcept-ness?

本文关键字:无例外 检测 何检测 叮当      更新时间:2023-10-16

我目前正在C++11中重新实现std::invoke(即理解和调整libc ++/libstdc++代码(,我偶然发现了一个与noexcept有关的问题。

这可以通过以下代码片段进行演示:

#include <functional>
void nothrow_method(int, int) noexcept
{
}
int main(int argc, char const *argv[])
{
static_assert(noexcept(std::__invoke(nothrow_method, 2, 3)), "");
static_assert(std::__is_nothrow_invocable<decltype(nothrow_method), int, int>::value, "");
}

我在 Debian Jessie 上,我的库是 libstdc++。

使用-std=c++14进行编译失败,并显示 clang 4.0.1,两者都static_assert触发。 但是,GCC 7.1.0没有问题。

我查看了libc ++如何实现std::invoke,并在我自己的实现中复制了他们检测noexcept的方式,但它仍然无法编译。

由于static_assert只有一条错误线,我真的不知道发生了什么,会不会与这篇博文中解释的内容有关?

我过去在noexcept和模板实例化点方面遇到了一些问题,但我很确定它在这里无关。

编辑:

我已经下载了libcxx主干,它在macOS 8.1.0上用apple-clang 10.12.6构建,尽管他们的代码在__invokenoexcept(noexcept()),但static_assert仍然会触发。

编辑2:

std::__*用于测试,我知道它们是私有的,但我不想发布我的invoke实现。

这似乎是Clang标准库的一个错误,可能在std::invoke<>和std::__is_nothrow_invocable<>的定义中...GCC正确地没有断言这两个语句,VS2017确实表现出该错误。

顺便说一句,您应该避免使用 std::__*<> 模板 — 它们不是标准的一部分,并且是标准库的私有模板。

下面是一个解决方法:您可以使用以下语法,该语法更正确,因为它会测试您将在应用程序中使用的实际语句。

#include <functional>
void nothrow_method(int, int) noexcept { }
int main()
{
static_assert(noexcept(nothrow_method(2, 3)), "");
return 0;
}