【问题标题】:How does `std::mem_fn` detect noexceptness in gcc 7.1.0`std::mem_fn` 如何在 gcc 7.1.0 中检测 noexceptness
【发布时间】:2018-03-28 13:59:40
【问题描述】:

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


更令人困惑的是,当我从https://wandbox.org/permlink/JUI3rsLjKRoPArAl 中删除一种方法上的 noexcept 说明符时,所有 noexcept 值都会发生变化,如此处https://wandbox.org/permlink/yBJ0R4PxzAXg09ef 所示。当一个是 noexcept 时,所有都是 noexcept。如何?这是一个错误吗?

【问题讨论】:

  • (顺便说一句,noexcept C++17中函数类型的一部分。)
  • @KerrekSB 但 cppreference 说它不在这里 en.cppreference.com/w/cpp/language/noexcept_spec?
  • 它说它不是直到 C++17类型的一部分。如果您在阅读时遇到问题,我无法帮助您。 >_>(我已经将“如何”编辑到之前的评论中。)
  • 对于c++14c++1z 一致性模式,您的示例代码在GCC 7.2 中的行为有所不同。关于 C++14 的问题还是很有趣的!
  • @Curious :在实际调查之后,我发现我错了。对造成的噪音和任何混乱表示歉意;我已经删除了误导性的 cmets。 (编辑:直到现在我才看到乔恩已经回答了你的问题。:-P)

标签: c++ c++11 g++ c++14 gcc7


【解决方案1】:

您在 C++14 模式下使用 GCC 看到的行为是一个错误,请参阅 https://gcc.gnu.org/PR77369

在您询问的 cmets 中:

还有mem_fn的声明,因为c++17没有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) );

不需要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 中修复(因此请升级您的编译器)。

【讨论】:

  • 谢谢!我有一种感觉,这是编译器中的一个错误!也许我真的误解了一些东西,但是当你传递一个指向成员函数的指针时,它会删除所有关于该方法在此之前是否为 noexcept 的编译时信息,对吗?在这种情况下,您已经对is_noexcept_callable 进行了模板化,因此类型系统中的信息仍然完好无损
  • 不,正如上面的 cmets 中反复指出的,“当你传递一个指向成员函数的指针时,该函数会清除所有关于该方法在此之前是否为 noexcept 的编译时信息” i> 在 C++17 中不正确。如果你有一个指向void (X::*)() noexcept 类型的成员函数的指针,那么信息不会被删除。如果您将其隐式转换为 void (X::*)()(这是允许的),那么您已经丢失了该信息。
  • 成员函数指针可以在运行时改变对吧?您如何跟踪 C++17 中方法的无异常性?
  • 因为 noexcept-ness 是类型的一部分。正如人们不断告诉你的那样。 void (X::*)() noexcept 是与 void (X::*)() 不同的类型。您可以更改 void(X::*)() noexcept 的值以指向不同的成员,但不能更改其类型,它始终是指向 noexcept 成员函数的指针。
  • 我对成员指针有一个可怕的误解(仔细想想,我的思路是 0 意义)。我假设 T en.cppreference.com/w/cpp/utility/functional/mem_fn 只是函数的返回类型,它包含所有函数类型信息(包括函数参数和函数的无异常性)。很抱歉!
猜你喜欢
  • 2023-03-21
  • 2012-07-25
  • 2020-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-18
相关资源
最近更新 更多