`std::mem_fn` 如何检测 gcc 7.1.0 中的异常情况
How does `std::mem_fn` detect noexceptness in gcc 7.1.0
在 gcc 7.1.0 中 std::mem_fn
能够检测成员函数指针上的 noexcept-ness。它是怎么做到的?我认为 noexcept
说明符不是函数类型的一部分?
更令人困惑的是,当我从 https://wandbox.org/permlink/JUI3rsLjKRoPArAl all the noexcept values change as seen here https://wandbox.org/permlink/yBJ0R4PxzAXg09ef 的一个方法上删除 noexcept 说明符时。当一个是 noexcept 时,所有都是 noexcept。如何?这是一个错误吗?
您在 C++14 模式下看到的 GCC 行为是一个错误,请参阅 https://gcc.gnu.org/PR77369
在你问的评论中:
Also the declaration of mem_fn since c++17 does not have a noexcept overload, then how does it detect this information from the user?
它不需要有 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) );
不需要 is_noexcept_callable
的 noexcept 重载,因为在 C++17 中,异常规范是类型的一部分,所以所有信息都已经编码在类型 T
中.当您使用指向 noexcept(true)
函数的指针实例化 std::mem_fn
时,它知道调用该函数不会抛出。当您使用 noexcept(false)
函数实例化它时,它知道它可能会抛出。
最后,您的示例无法使用 GCC 7.1 在 C++17 模式下编译的原因是 https://gcc.gnu.org/PR80478,它已在 GCC 7.2 中修复(因此请升级您的编译器)。
在 gcc 7.1.0 中 std::mem_fn
能够检测成员函数指针上的 noexcept-ness。它是怎么做到的?我认为 noexcept
说明符不是函数类型的一部分?
更令人困惑的是,当我从 https://wandbox.org/permlink/JUI3rsLjKRoPArAl all the noexcept values change as seen here https://wandbox.org/permlink/yBJ0R4PxzAXg09ef 的一个方法上删除 noexcept 说明符时。当一个是 noexcept 时,所有都是 noexcept。如何?这是一个错误吗?
您在 C++14 模式下看到的 GCC 行为是一个错误,请参阅 https://gcc.gnu.org/PR77369
在你问的评论中:
Also the declaration of mem_fn since c++17 does not have a noexcept overload, then how does it detect this information from the user?
它不需要有 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) );
不需要 is_noexcept_callable
的 noexcept 重载,因为在 C++17 中,异常规范是类型的一部分,所以所有信息都已经编码在类型 T
中.当您使用指向 noexcept(true)
函数的指针实例化 std::mem_fn
时,它知道调用该函数不会抛出。当您使用 noexcept(false)
函数实例化它时,它知道它可能会抛出。
最后,您的示例无法使用 GCC 7.1 在 C++17 模式下编译的原因是 https://gcc.gnu.org/PR80478,它已在 GCC 7.2 中修复(因此请升级您的编译器)。