如何为noexcept函数指针创建别名?

Mic*_*nda 11 c++ function-pointers noexcept c++11

我想这样做:

using function_type = void (*)(void*)noexcept;
Run Code Online (Sandbox Code Playgroud)

但是我收到错误"类型别名中不允许出现异常规范." (Xcode 6.1版中的clang)

有没有使用noexcept说明符创建别名的解决方法?

我正在寻找一些适用于跨平台功能的语言(不是扩展)定义的东西.

Pra*_*ian 11

该标准明确禁止异常规范出现在typedef别名或别名声明中.但它也声明异常说明符可能出现在函数指针类型中.

§15.4/ 2 [except.spec]

一个异常规范应仅在出现一个函数声明为函数类型,函数指针类型,参照功能类型或成员函数指针类型,它是一个声明或定义,的顶级类型或上这样一种类型在函数声明符中作为参数或返回类型出现.一个异常规范,不得出现在typedef声明或别名声明.

如果指向函数的指针确实有异常规范,那么必须始终为该函数指针分配一个具有兼容异常规范的函数类型.

§15.4/ 5

...类似的限制适用于对函数指针的赋值和初始化,指向成员函数的指针以及对函数的引用:目标实体应至少允许赋值或初始化中源值允许的异常....

使用这两个,您可以noexcept以环形交叉方式将规范引入函数指针类型.

void (*foo_ptr)(void *) noexcept = nullptr;
using function_type = decltype(foo_ptr);
Run Code Online (Sandbox Code Playgroud)

现在,您无法将没有noexcept(true)规范的函数分配给类型的函数指针function_type.clang将无法使用错误编译代码

错误:目标异常规范不是源的超集

  • 知道这个限制的理由是什么吗? (3认同)
  • 这个解决方法看起来更像是一个 Clang bug,而不是预期的行为。 (2认同)
  • @Praetorian好吧,如果异常规范不是类型的一部分,那么`decltype`(返回实体的类型)不应该返回它...... (2认同)
  • C++17 将异常规范作为类型的一部分 (2认同)

Rei*_*ica 7

作为这个答案的推论,您寻求的模式很简单:

using function_type = decltype(std::declval<function_type_declaration>());
Run Code Online (Sandbox Code Playgroud)

IE

#include <utility>
//...
using function_type = decltype(std::declval<void (*)(void*)noexcept>());
Run Code Online (Sandbox Code Playgroud)

这不适用于链接extern,包括extern "C",即:

// INVALID
using function_type = decltype(std::declval<extern "C" void(*)(void)>());

// WORKAROUND
extern "C" void function_type_dummy(void);
using function_type = decltype(&function_type_dummy);
Run Code Online (Sandbox Code Playgroud)


Mic*_*nda 6

Praetorian 答案的替代方法,不涉及声明变量:

void unused_function(void*)noexcept;
using function_type = decltype(&unused_function);
Run Code Online (Sandbox Code Playgroud)

unused_function声明,但没有定义。

  • 感谢 `declval`,有一种方法可以匿名声明它:) (2认同)