`std :: mem_fn`如何在gcc 7.1.0中检测noexceptness

Cur*_*ous 3 c++ g++ c++11 c++14 gcc7

使用gcc 7.1.0 std::mem_fn能够检测成员函数指针上的noexcept-ness.它是如何做到的?我认为说明noexcept符不是函数类型的一部分?


更令人困惑的是,当我从https://wandbox.org/permlink/JUI3rsLjKRoPArAl中移除一个方法上的noexcept说明符时,所有noexcept值都会发生变化,如https://wandbox.org/permlink/yBJ0R4PxzAXg09ef所示.当一个人不是新的时候,所有人都不是例外.怎么样?这是一个错误吗?

Jon*_*ely 6

您在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) );
Run Code Online (Sandbox Code Playgroud)

没有必要进行noexcept重载,is_noexcept_callable因为在C++ 17中,异常规范是类型的一部分,因此所有信息都已经在类型中编码T.当您std::mem_fn使用指向noexcept(true)函数的指针进行实例化时,它知道调用该函数不能抛出.当您使用noexcept(false)函数实例化它时,它知道它可能会抛出.

最后,您的示例无法在C++ 17模式下使用GCC 7.1编译的原因是https://gcc.gnu.org/PR80478,它已在GCC 7.2中修复(因此升级您的编译器).