我想这样做:
using function_type = void (*)(void*)noexcept;
但是我收到错误"类型别名中不允许出现异常规范。" (在Xcode版本6.1中的clang)
是否有使用noexcept说明符创建别名的解决方法?
我正在寻找能够跨语言(而非扩展)定义的跨平台功能的东西。
答案 0 :(得分:9)
标准明确禁止异常规范出现在typedef
或别名声明中。但它也声明异常说明符可能出现在函数指针类型中。
§15.4/ 2 [except.spec]
异常规范仅出现在函数类型的函数声明符中,指向函数类型的指针,对函数类型的引用,或指向成员函数类型的指针,它是声明或定义的顶级类型,或者是在函数声明符中作为参数或返回类型出现的类型。 例外规范不得出现在
typedef
声明或别名声明 中。
如果指向函数的指针确实有异常规范,那么必须始终为该函数指针分配一个具有兼容异常规范的函数类型。
§15.4/ 5
...
类似的限制适用于对指针的赋值和初始化 函数,指向成员函数的指针以及对函数的引用:目标实体应至少允许在赋值或初始化中使用源值允许的异常。...
使用这两个,您可以以环形方式将noexcept
规范引入函数指针类型。
void (*foo_ptr)(void *) noexcept = nullptr;
using function_type = decltype(foo_ptr);
现在,您无法将没有noexcept(true)
规范的函数分配给类型为function_type
的函数指针。 clang will fail to compile带错误的代码
错误:目标异常规范不是源的超集
答案 1 :(得分:3)
Praetorian答案的替代方案,其中没有涉及声明变量:
void unused_function(void*)noexcept;
using function_type = decltype(&unused_function);
声明unused_function
,但未定义。
答案 2 :(得分:2)
作为this answer的必然结果,您寻求的模式很简单:
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);
答案 3 :(得分:0)
作为this answer的进一步简化,我们可以如下使用特征类型std::add_pointer
:
using function_type = std::add_pointer_t<void(void*) noexcept>;
来自cppreference文档(重点是我的):
如果T是引用类型,则提供成员typedef类型,该类型是指向引用类型的指针。
否则,如果T命名为对象类型,则非cv或ref限定的函数类型,或(可能是cv限定的)无效类型,则提供成员typedef类型,该类型为类型T *。
否则(如果T是cv或ref限定的函数类型),则提供成员typedef类型,即类型T。
换句话说,std::add_pointer
的实现方式与Function signature-like expressions as C++ template arguments兼容。
extern "C"
函数的限制仍然适用,因此您需要在我链接的答案中使用替代方法。