在声明中使用不一致的 noexcept 是否违反 ODR?

Bee*_*ope 3 c c++ one-definition-rule language-lawyer noexcept

这是一个两部分的问题,第一部分是关于完全用 C++ 编写的东西,第二部分是关于用 C 编写但从 C++ 调用的函数之间的交互。

第1部分

让不同的翻译单元noexcept在同一函数的声明中看到不同的说明符是 ODR 还是其他违规行为?具体来说,如果一个单位看到:

void foo();
Run Code Online (Sandbox Code Playgroud)

而另一个人看到:

void foo() noexcept;
Run Code Online (Sandbox Code Playgroud)

这是 ODR 还是其他违规行为?您可能会假设该函数实际上永远不会抛出(即,它实际上可以被声明noexcept)。

第2部分

如果所有 C++ 代码都将声明视为extern "C" void foo() noexcept;,但该函数实际上是在 C 中定义(实现)的,其中声明(显然)不包含noexcept?

eer*_*ika 7

这是 ODR ... 违规吗?

这不是 ODR 违规。这些:

void foo();
void foo() noexcept;
Run Code Online (Sandbox Code Playgroud)

只是声明。它们不是定义,一个定义规则并不限制它们。

这是……其他违规行为吗?

是的。它违反了以下规则(引自最新的标准草案):

[除.spec]

如果函数的声明没有 noexcept 说明符,则该声明具有潜在的抛出异常规范,除非[不适用的异常],在这种情况下,异常规范如下所述,并且该函数的其他声明不应具有一个 noexcept 说明符。... 仅当单个翻译单元中的异常规范不相同时才需要诊断。


如果所有 C++ 代码都将声明视为 extern "C" void foo() noexcept;,但该函数实际上是在 C 中定义(实现)的,其中声明(显然)不包含 noexcept,是否违反?

技术上也许。但是 C++ 标准并不真正适用于 C,所以这可能是指定不足的。即使程序在技术上格式错误,如果一个 TU 认为一个函数noexcept只要该函数从不抛出,我也不确定是否存在任何实际问题。

值得一提的是,glibcthrow()仅在包含到 C++ 中时才在使用 GCC 时声明标准 C 函数。