"noreturn"是函数签名的一部分吗?

9

[dcl.attr.noreturn]可以用来标记一个函数不返回任何值。

[[ noreturn ]] void f() {
    throw "error";
}

[[noreturn]]是函数标识/签名的一部分吗?在编译时能否检测到函数是否为[[noreturn]]呢?

例如,

static_assert(is_noreturn(f));

如果不是这样的话,我应该采用一个约定并定义一个标签结构吗?
struct noreturn_{noreturn_()=delete;};
...
[[noreturn]] noreturn_ f(){throw "error";}
2个回答

8
"signature"有一个非常精确的定义。好的,具体取决于你所讨论的内容类型
  • ⟨函数⟩ 名称、参数类型列表([dcl.fct])、所属命名空间(如果有)、尾随的requires-clause([dcl.decl])(如果有)
  • ⟨函数模板⟩ 名称、参数类型列表([dcl.fct])、所属命名空间(如果有)、返回类型、template-head和尾随的requires-clause([dcl.decl])(如果有)
  • ⟨函数模板特化⟩ 它是一个特化模板的签名以及它的模板参数(无论是显式指定还是推导出来的)
  • ⟨类成员函数⟩ 名称、参数类型列表([dcl.fct])、函数所属的类、cv-qualifiers(如果有)、ref-qualifier(如果有)和尾随的requires-clause([dcl.decl])(如果有)
  • ⟨类成员函数模板⟩ 名称、参数类型列表([dcl.fct])、函数所属的类、cv-qualifiers(如果有)、ref-qualifier(如果有)、返回类型(如果有)、template-head和尾随的requires-clause([dcl.decl])(如果有)
  • ⟨类成员函数模板特化⟩ 它是一个特化的成员函数模板的签名以及它的模板参数(无论是显式指定还是推导出来的)

属性不属于它们中的任何一个。

[[noreturn]] 也不是类型的一部分。它适用于函数,而不是它的类型。


在编译时能检测到一个函数是否为noreturn吗?

不行。委员会为属性建立的规则是,“使用所有特定属性的实例编译一个有效程序必须导致原始程序的正确解释”。如果您可以编程地检测到属性的存在,则该规则将无法保持。


如果不是这样的话,我是否应该采用一种约定并定义一个标记结构体?
这样的标记有什么用处尚不清楚。

"目前尚不清楚这种标记有什么用处。 " 这是关于通用代码的,我想从一组函数返回中构建一个变体,并留下其中一些未实现(在运行时抛出),无论这些函数返回什么,我都不想将其添加到变体中。 在某种意义上,我必须区分真正执行返回“void”的函数和永远不会成为返回函数的形式“void”返回。请参见此处的技术:https://arne-mertz.de/2018/06/functions-of-variants-are-covariant/,并阅读至末尾。" - alfC

5
如果这是类型的一部分,一个正确的类型检查编译器将不会接受例如以下内容:
[[noreturn]] int f(void);
int (*fp)(void) = f;

上述内容编译无误。 [[noreturn]]不是类型的一部分。(顺便提一下,在C11中,_Noreturn也不是类型的一部分,它在语法上与inline处于同一类别。) 至于如何检测它,在C++11标准草案中我没有找到任何机制。您可以采用您提出的约定来检测它,但您将受限于遵循此约定的函数。

1
好的,noexcept是函数类型的一部分,因此可以是noreturn。即使它不是类型的一部分,在原则上也可以在编译时检测到。https://en.cppreference.com/w/cpp/language/noexcept_spec - alfC
@alfC int f(void) noexcept; int (*fp)(void) = f; 在我的 g++无法编译 - Petr Skocik
1
要么是你的编译器出了问题,要么是你的测试有误。 - T.C.
假设noreturn是类型的一部分,那么赋值可以通过类型检查。试着换个方式。 - Joshua
在编译器中,我使用的是gcc 8int (*fp)(void) noexcept; fp = f;int (*fp)(void); fp = f;都可以编译通过。这是一个很好的例子,说明noexcept可以被检测到,但它不是函数类型的一部分。因此,在原则上也可以使用noreturn - alfC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接