【问题标题】:How does clang detect noexcept-ness?clang如何检测noexcept-ness?
【发布时间】:2018-02-02 22:43:39
【问题描述】:

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

这可以用下面的 sn-p 来证明:

#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只有一个错误行,我真的不知道发生了什么,会不会与blog post中的解释有关?

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

编辑:

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

EDIT2:

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

【问题讨论】:

  • 来自您链接的文章:Note: clang currently has a bug where noexcept does not yield true even though the expression checked is a constant-expression. A workaround is available in the appendix of this post.
  • 在C++17之前noexcept不是函数类型的一部分,所以void nothrow_method(int, int) noexcept;void throwing_method(int, int);具有相同的类型。
  • @tkausl 我看不出它如何与那个问题联系起来,因为我不处理常量表达式。
  • @cpplearner 确实,但我已经看到 __invoke 自 C++03 以来被 libc++ 和 libstdc++ 内部使用(至少对于前者)。我再次检查,有一个宏_LIBCXX_INVOKE_RETURN 处理noexcept(noexcept(...)) 子句、尾随返回类型和调用本身。我在 libcxx 测试套件中看到了 noexcept 测试和 invoke,我确信它们的实现是正确的......我将尝试在 macOS 上使用 clang 编译并发布我的结果。
  • std::__* 对 stl 和 std::invoke() 和 std::is_no_throw_invokable c++17 特性的实现不是私有的吗?调用标准外的元函数就近乎UB了,这不禁让人理解....

标签: c++ templates c++14 metaprogramming


【解决方案1】:

这似乎是 Clang 标准库的一个错误,可能在 std::invoke 和 std::__is_nothrow_invocable 的定义中...错误。

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

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

#include <functional>

void nothrow_method(int, int) noexcept { }

int main()
{
    static_assert(noexcept(nothrow_method(2, 3)), "");
    return 0;
}

【讨论】:

  • 我知道永远不应该这样做,这只是为了测试目的,因为我正在重新实现invoke,正如我在帖子顶部提到的那样(我应该坚持对混淆感到抱歉) .所以我感兴趣的一点是invoke 的无例外性。我目前正在构建最新的 clang/libcxx 以查看它是否已修复,这可能是因为它适用于 GCC 的编译器内部特性。
  • 我检查了 vs2017 的调用,因为它也使 static_assert 失败。它确实有一个 noexcept 子句,这很奇怪。更正:std::invoke not 是否有 noexcept 子句。
  • 感谢您查看 VS!我在最新的 libc++/clang 上没有成功...我倾向于内部编译器使 GCC 工作。
猜你喜欢
  • 2020-05-11
  • 2011-06-08
  • 2015-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-04
  • 2014-10-12
  • 2019-09-22
相关资源
最近更新 更多