C++17 异常说明符类型系统将如何工作?

How will C++17 exception specifier type system work?

学习一下"noexcept specifier(and operator)",写了个简单的代码。我很惊讶这段代码:

void asdf() noexcept {}
int main() 
{
    auto f = asdf;
    std::cout << std::boolalpha << noexcept(f()) << std::endl;
}

打印 false,甚至函数 "asdf" 也没有指定。

所以在寻找为什么会发生这种神秘现象时,我发现了 C++17 的 "exception specifier type system"- P0012R1.

根据这个(已接受的)提案,自 C++17 起;由于 noexcept 是函数类型的一部分,上面的代码会打印 true?

还有一个,在问题的一行中:

std::function<void() noexcept> f

noexcept 指定在 C++14 或 11 中似乎被忽略了。 此代码在 C++17 中是否会按预期工作?

According to this (accepted) proposal, since C++17; as noexcept is part of function type, will the code above print true?

是。

f 的类型将被推断为 void(*)() noexcept,因为应用于 asdf 的函数到指针的转换将保留 noexcept 属性 .对 noexcept 函数指针的调用肯定不会抛出异常,除非它的子表达式之一抛出异常。

确切的措辞,参见[expr.unary.noexcept]/3 and [expect.spec]/13。请注意,C++17 草案后一段中的新措辞来自 P0012R1,在 OP 中有链接。

The result of the noexcept operator is true if the set of potential exceptions of the expression ([except.spec]) is empty, and false otherwise.

...

  • If e is a function call ([expr.call]):
    • If its postfix-expression is a (possibly parenthesized) id-expression ([expr.prim.id]), class member access ([expr.ref]), or pointer-to-member operation ([expr.mptr.oper]) whose cast-expression is an id-expression, S is the set of types in the exception specification of the entity selected by the contained id-expression (after overload resolution, if applicable). ...

所以 f() 的潜在异常集与 f 的异常规范中的类型集相同,后者是空的,因为 f 被声明为 [=14] =].

我们继续第二个问题:

The noexcept specifying seems ignored in C++14 or 11. Will this code work as intended in C++17?

您的问题似乎是:std::function<void() noexcept> 会拒绝持有可以抛出异常的函数吗?

我会说不清楚。在目前的标准措辞中,std::function<void() noexcept>实际上并没有定义,就像std::function<double(float) const> is not defined一样。这在 C++14 中当然不是问题,因为 noexcept 不被视为函数类型的一部分。

std::function<void() noexcept> 会在 C++17 中简单地中断吗?这对我来说是不确定的。让我们看一下当前的措辞来猜测 "should" 的行为是什么。

标准要求 std::function<R(ArgTypes..)> 的构造函数的参数为​​ "Lvalue-Callable" 参数类型 ArgTypes... 和 return 类型 Rmeans:

A callable type ([func.def]) F is Lvalue-Callable for argument types ArgTypes and return type R if the expression INVOKE(declval<F&>(), declval<ArgTypes>()..., R), considered as an unevaluated operand (Clause [expr]), is well formed ([func.require]).

也许应该有一个额外的要求,如果函数类型是noexcept,那么noexcept(INVOKE(...))也必须为真。尽管如此,这个措辞并没有出现在当前的草案中。

在P0012R1中,有一条评论是:

It is an open issue how to propagate "noexcept" through std::function.

我的猜测是,他们的意思是,如果施加此附加要求,则不清楚如何实施 std::function。希望其他人可以提供更多详细信息。