您在 C++14 模式下使用 GCC 看到的行为是一个错误,请参阅https://gcc.gnu.org/PR77369
在你问的评论中:
此外,自 c++17 以来 mem_fn 的声明没有 noexcept 重载,那么它如何从用户那里检测到这些信息?
它不需要有一个 noexcept 重载,考虑这个 C++17 代码:
template<typename T>
constexpr bool is_noexcept_callable(T t) {
return noexcept(t());
}
void f() noexcept { }
void g() { }
static_assert( is_noexcept_callable(f) );
static_assert( !is_noexcept_callable(g) );
不需要有 noexcept 重载,is_noexcept_callable
因为在 C++17 中,异常规范是类型的一部分,所以所有信息都已经编码在 type 中T
。当您使用指向函数std::mem_fn
的指针进行实例化时,noexcept(true)
它知道调用该函数不能抛出。当你用一个noexcept(false)
函数实例化它时,它知道它可能会抛出。
最后,您的示例无法使用 GCC 7.1 在 C++17 模式下编译的原因是https://gcc.gnu.org/PR80478已在 GCC 7.2 中修复(因此请升级您的编译器)。