在编译指向可能抛出的函数的非抛出指向时,gcc 有什么问题吗?

Is there anything wrong with gcc when compiling a nonthrowing pointing to a function which might throw?

我已经阅读了《C++ Primer》第 5 版这本书。在异常规范和指针、虚拟和复制控制部分,它说:

That is, if we declare a pointer that has a nonthrowing exception specification, we can use that pointer only to point to similarly qualified functions.

我也参考了noexcept specifier (since C++11),还有类似的:

Pointers to non-throwing functions are implicitly convertible (since C++17)can be assigned (until C++17) to pointers to potentially-throwing functions, but not the other way around.

void ft(); // potentially-throwing
void (*fn)() noexcept = ft; // error

当我用 gcc version 5.4.0 20160609 编译示例片段时,没有错误或警告。
但是当我用 Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x86 编译它时,它会抱怨 error C2440: 'initializing': cannot convert from 'void (__cdecl *)(void)' to 'void (__cdecl *)(void) noexcept'。这似乎是正确的行为。

所以我想知道 gcc 编译器有什么问题吗?

根据 this page,C++17 功能 "Make exception specifications be part of the type system" 从 GCC 7.0 开始可用。

历史上,exception specifiers have not been part of the type system

  1. Should exception-specifications be part of the type system?

[…]

EWG determined that no action should be taken on this issue.

这确实有点令人惊讶。这不是类型系统中的漏洞,因为类型仍然在 运行 时间检查(必要时导致异常翻译)。

但是,这个问题在 P0012R1 and merged into the standard with this commit 中再次出现:

commit 6e75f2d588a4b1b0c220eb8eec4b9ad8cb6107f3
Author: Dawn Perchik <dperchik@embarcadero.com>
Date:   Thu Oct 29 12:11:02 2015 -0700

    P0012R1 Make exception specifications be part of the type system, version 5

所以它不在 C++14 中,但会在 C++17 中。通常,在编译器实现新的语言功能之前会有一些滞后。

海湾合作委员会错误。这也不是有效的 C++11/14。 N3337 [except.spec]/5,强调我的:

If a virtual function has an exception-specification, all declarations, including the definition, of any function that overrides that virtual function in any derived class shall only allow exceptions that are allowed by the exception-specification of the base class virtual function. [ Example: ... — end example ] A similar restriction applies to assignment to and initialization of pointers to functions, pointers to member functions, and references to functions: the target entity shall allow at least the exceptions allowed by the source value in the assignment or initialization.

这就是人们说 C++17 之前的异常规范是 "shadow type system" 的意思:它们不是实际类型的一部分,但在多个上下文中表现(初始化、赋值、虚拟覆盖)就好像它们一样。