我想这样做:
using function_type = void (*)(void*)noexcept;
但我收到一个错误“类型别名中不允许异常规范”。(Xcode 6.1 版本中的 clang)
是否有一种解决方法可以使用 noexcept 说明符创建别名?
我正在寻找跨平台功能的语言(不是扩展)定义的东西。
我想这样做:
using function_type = void (*)(void*)noexcept;
但我收到一个错误“类型别名中不允许异常规范”。(Xcode 6.1 版本中的 clang)
是否有一种解决方法可以使用 noexcept 说明符创建别名?
我正在寻找跨平台功能的语言(不是扩展)定义的东西。
该标准明确禁止异常规范出现在typedef
别名或别名声明中。但它也指出异常说明符可能出现在函数指针类型中。
§15.4/2 [除了.spec]
异常规范应仅出现在函数类型的函数声明符、指向函数类型的指针、对函数类型的引用或指向作为声明或定义的顶级类型的成员函数类型的指针上,或出现在此类类型上在函数声明器中作为参数或返回类型出现。异常规范不应出现在
typedef
声明或别名声明中。
如果指向函数的指针确实具有异常规范,则必须始终为该函数指针分配具有兼容异常规范的函数类型。
§15.4/5
...
类似的限制适用于函数指针、成员函数指针和函数引用的赋值和初始化:目标实体应至少允许赋值或初始化中源值允许的异常。...
使用这两个,您可以noexcept
以迂回的方式将规范转换为函数指针类型。
void (*foo_ptr)(void *) noexcept = nullptr;
using function_type = decltype(foo_ptr);
现在,您不能将没有noexcept(true)
规范的函数分配给 type 的函数指针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>());
IE
#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>;
从 cppreference 文档(强调我的):
如果 T 是引用类型,则提供成员 typedef type,它是指向被引用类型的指针。
否则,如果 T 命名一个对象类型,一个不是 cv 或 ref 限定的函数类型,或者一个(可能是 cv 限定的)void 类型,则提供类型为 T* 的成员 typedef type。
否则(如果 T 是 cv 或 ref 限定的函数类型),则提供类型 T 的成员 typedef type。
换句话说,它的实现方式与作为 C++ 模板参数的类函数签名表达式std::add_pointer
兼容。
对功能的限制extern "C"
仍然适用,因此您需要在我链接的答案中使用解决方法。