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

How do I create an alias for a noexcept function pointer?

本文关键字:指针 创建 别名 函数 noexcept      更新时间:2023-10-16

我想这样做:

using function_type = void (*)(void*)noexcept;

但是我收到一个错误"类型别名中不允许异常规范"。(在 Xcode 6.1 版本中的 clang (

是否有解决方法可以创建带有 noexcept 说明符的别名?

我正在寻找由跨平台功能的语言(而不是扩展(定义的东西。

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

§15.4/2 [规格除外]

异常规范应仅出现在函数类型的函数声明符、指向函数类型的指针、对函数类型的引用或指向作为声明或定义的顶级类型的成员函数类型的指针上,或者出现在函数声明符中显示为参数或返回类型的此类类型上。例外规范不得出现在typedef声明或别名声明

如果指向函数的指针

确实具有异常规范,则必须始终为该函数指针分配具有兼容异常规范的函数类型。

§15.4/5

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

使用这两个,您可以以迂回的方式将noexcept规范转换为函数指针类型。

void (*foo_ptr)(void *) noexcept = nullptr;
using function_type = decltype(foo_ptr);

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

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

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

void unused_function(void*)noexcept;
using function_type = decltype(&unused_function);

已声明unused_function,但未定义。

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

using function_type = decltype(std::declval<function_type_declaration>());

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

不适用于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);

为了进一步简化这个答案,我们可以按如下方式使用类型特征std::add_pointer

using function_type = std::add_pointer_t<void(void*) noexcept>;

来自 cpp首选项文档(强调我的(:

如果 T 是引用类型,则提供成员 typedef 类型,该类型是指向引用类型的指针。

否则,如果 T 命名对象类型,则不是 cv 或 ref 限定的函数类型,或(可能符合 cv 限定的(void 类型,则提供成员类型定义类型,即类型 T*。

否则(如果 T 是 cv 或 ref 限定的函数类型(,则提供成员 typedef 类型,该类型为 T。

换句话说,std::add_pointer的实现方式使其与类似函数签名的表达式兼容,如C++模板参数。

extern "C"函数的限制仍然适用,因此您需要使用我链接的答案中的解决方法。