调用指向成员函数后,noexcept运算符失败

时间:2017-10-12 22:25:07

标签: c++ clang noexcept

这个MWE可能看似人为,但是失败的static_assert仍然令人惊讶:

#include <utility>

struct C {
  void f() noexcept { }
  using F = void(C::*)();

  static constexpr F handler() noexcept {
    return &C::f;
  }

  void g() noexcept(noexcept((this->*handler())())) {
  }
};

int main() {
  static_assert(noexcept(std::declval<C>().g()));
}

Wandbox链接:https://wandbox.org/permlink/a8HSyfuyX1buGrbZ

我希望这可以用于Clang而不是GCC,因为他们对&#34;这个&#34;在运算符noexcept的上下文中。

2 个答案:

答案 0 :(得分:7)

看到你的static_assert没有字符串参数,你正在使用C ++ 17。在C ++ 17中,noexcept成为类型系统的一部分。这意味着什么:

using F = void(C::*)();

此PMF不是noexcept。调用它等同于调用noexcept(false)成员函数。您需要将函数类型标记为noexcept

using F = void(C::*)() noexcept;

该更改允许您的代码编译:

#include <utility>

struct C {
  void f() noexcept { }
  using F = void(C::*)() noexcept;

  static constexpr F handler() noexcept {
    return &C::f;
  }

  void g() noexcept(noexcept((this->*handler())())) {
  }
};

int main() {
  static_assert(noexcept(std::declval<C>().g()));
}

On Godbolt

答案 1 :(得分:3)

fnoexcept,但指向它的指针不是。因此,在g的定义中,this->*handler()返回的PMF不是noexcept(即使您碰巧返回了 {{{ 1}},所以当您通过编写noexcept来调用它时,您调用的函数不是(this->*handler())(),因此noexcept子句返回noexcept

false添加到第5行的末尾,然后就可以了。