我意识到我可以通过使用声明一个指向noexcept函数的指针的类型,但是如果我使用typedef则禁止这样的声明.请考虑以下代码:
#include <iostream>
using fptr = void(*)() noexcept;
// typedef void(*FPTR)() noexcept; // fails to compile
void f() noexcept
{
std::cout << "void f() noexcept" << std::endl;
}
void g()
{
std::cout << "void g()" << std::endl;
throw 10;
}
int main()
{
fptr f1 = f;
fptr f2 = g; // why can we do this?
try {
f1();
f2();
}
catch (...)
{
std::cout << "Exception caught" << std::endl;
}
}
如果我取消注释FPTR声明,我就会得到
error: 'FPTR' declared with an exception specification
但是,使用效果很好.用gcc4.9和gcc5编译.
我的问题是:
>为什么这种不一致?
>为什么我们甚至可以使用noexcept使用,因为我们可以将指针绑定到未声明为noexcept的函数,如行fptr f2 = g;
似乎是一个与gcc相关的bug,即使gcc5也没有抓住它.填写错误报告
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65382
这似乎是海湾合作委员会的一个错误; Clang拒绝两者,因为类型别名或typedef中不允许使用异常规范.这可以在以下位置找到:
15.4 Exception specifications [except.spec]
2 An exception-specification shall appear only on a function declarator for a function type,pointer to function type,reference to function type,or pointer to member function type that is the top-level type of a declaration or definition,or on such a type appearing as a parameter or return type in a function declarator. An exception-specification shall not appear in a typedef declaration or alias-declaration.
[…]
该标准还明确指出两者应该是一致的:
7.1.3 The typedef
specifier [dcl.typedef]
2 A typedef-name can also be introduced by an alias-declaration. The identifier following the using
keyword becomes a typedef-name and the optional attribute-specifier-seq following the identifier appertains to that typedef-name. It has the same semantics as if it were introduced by the typedef
specifier. In particular,it does not define a new type and it shall not appear in the type-id.
(强调我的)
回答你的第二个问题:GCC可能只是忽略了异常规范,因为函数不能仅仅在异常规范上重载 – 它不是函数签名的一部分.这可以在这里找到:
8.3.5 Functions [dcl.fct]
6 […] The return type,the parameter-type-list,the ref-qualifier,and the cv-qualifier-seq,but not the default arguments (8.3.6) or the exception specification (15.4),are part of the function type. [ Note: Function types are checked during the assignments and initializations of pointers to functions,references to functions,and pointers to member functions. — end note ]