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

时间:2014-12-15 17:23:05

标签: c++ c++11 function-pointers noexcept

我想这样做:

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

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

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

我正在寻找能够跨语言(而非扩展)定义的跨平台功能的东西。

4 个答案:

答案 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"函数的限制仍然适用,因此您需要在我链接的答案中使用替代方法。