【发布时间】: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