C ++ 17异常说明符类型系统将如何工作? [英] How will C++17 exception specifier type system work?
问题描述
研究"noexcept说明符(和运算符)",我编写了一个简单的代码.我很惊讶这段代码:
Studying about "noexcept specifier(and operator)", I wrote a simple code. And I am surprised that this piece of code:
void asdf() noexcept {}
int main()
{
auto f = asdf;
std::cout << std::boolalpha << noexcept(f()) << std::endl;
}
打印false
,即使函数"asdf"也没有指定例外.
prints false
, even function "asdf" is noexcept-specified.
因此,在搜寻为什么发生这种神秘现象的过程中,我发现了C ++ 17的异常说明符类型系统"-
So while searching why this mysterious phenomenon is happening, I found C++17's "exception specifier type system"- P0012R1.
根据该(接受的)建议,自C ++ 17起;由于noexcept
是函数类型的一部分,因此上面的代码会打印true
吗?
According to this (accepted) proposal, since C++17; as noexcept
is part of function type, will the code above print true
?
还有一个问题,在此问题的一行中:
And one more, in this question's one line:
std::function<void() noexcept> f
在C ++ 14或11中似乎忽略了noexcept
的指定.
这段代码能按C ++ 17的预期运行吗?
The noexcept
specifying seems ignored in C++14 or 11.
Will this code work as intended in C++17?
推荐答案
根据该(接受的)建议,自C ++ 17起;因为noexcept是函数类型的一部分,所以上面的代码会打印
true
吗?
是的.
f
的类型将推导为void(*)() noexcept
,因为应用于asdf
的函数到指针的转换将保留noexcept
属性.除非对它的子表达式之一进行调用,否则对noexcept
函数指针的调用肯定不会引发异常.
The type of f
will be deduced to void(*)() noexcept
since the function-to-pointer conversion applied to asdf
will preserve the noexcept
property. A call to a noexcept
function pointer certainly cannot throw an exception, unless one of its subexpressions does.
有关确切的措辞,请参见 [expr.unary.noexcept]/3 和 [expect.spec]/13 .请注意,C ++ 17草案后面的段落中的新措词来自于OP中链接的P0012R1.
For the exact wording, see [expr.unary.noexcept]/3 and [expect.spec]/13. Note that the new wording in the latter paragraph from the C++17 draft comes from P0012R1, which is linked in the OP.
如果表达式的潜在异常集([except.spec])为空,则
noexcept
运算符的结果为true
,否则为false
.
The result of the
noexcept
operator istrue
if the set of potential exceptions of the expression ([except.spec]) is empty, andfalse
otherwise.
...
- 如果
e
是函数调用([expr.call]):- 如果其 postfix-expression 是(可能带有括号) id-expression ([expr.prim.id]),则类成员访问权限([expr.ref] )或指向成员的指针操作([expr.mptr.oper]),其中 cast-expression 是 id-expression , S 是由包含的 id-expression 选择的实体的异常规范中的一组类型(在重载解析之后,如果适用). ...
- 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
被声明为noexcept
,因此它为空.So the set of potential exceptions of
f()
is the same as the set of types in the exception specification off
, which is empty sincef
is declarednoexcept
.让我们继续第二个问题:
Let's move on to the second question:
noexcept
指定似乎在C ++ 14或11中被忽略.此代码是否可以在C ++ 17中正常工作?The
noexcept
specifying seems ignored in C++14 or 11. Will this code work as intended in C++17?您的问题似乎是:
std::function<void() noexcept>
会拒绝保留可能引发异常的函数吗?Your question seems to be: will
std::function<void() noexcept>
refuse to hold a function that can throw exceptions?我会说这是不清楚的.在标准的当前措辞中,实际上并未定义
std::function<void() noexcept>
,就像I would say that it's unclear. In the present wording of the standard,
std::function<void() noexcept>
is not actually defined, just asstd::function<double(float) const>
is not defined. This was of course not an issue in C++14, sincenoexcept
was not considered part of a function's type.std::function<void() noexcept>
会在C ++ 17中中断吗?这对我来说并不确定.让我们看一下当前的措辞,以猜测行为应该"是什么.Will
std::function<void() noexcept>
simply break in C++17? That's uncertain to me. Let's take a look at the current wording to guess what the behaviour "should" be.该标准要求
std::function<R(ArgTypes..)>
的构造函数的参数对于参数类型ArgTypes...
必须是左值可调用的",并返回类型R
,其中The standard requires the argument to the constructor of
std::function<R(ArgTypes..)>
to be "Lvalue-Callable" for argument typesArgTypes...
and return typeR
, which means:参数类型
ArgTypes
的可调用类型([func.def])F
是 Lvalue-Callable ,如果表达式INVOKE(declval<F&>(), declval<ArgTypes>()..., R)
被视为未求值,则返回类型R
操作数(子句[expr])格式正确([func.require]).A callable type ([func.def])
F
is Lvalue-Callable for argument typesArgTypes
and return typeR
if the expressionINVOKE(declval<F&>(), declval<ArgTypes>()..., R)
, considered as an unevaluated operand (Clause [expr]), is well formed ([func.require]).也许应该另外要求,如果函数类型为
noexcept
,则noexcept(INVOKE(...))
也必须为true.但是,该措词在当前草案中不存在.Perhaps there should be an additional requirement that if the function type is
noexcept
, thennoexcept(INVOKE(...))
must be true as well. Nonetheless, this wording is not present in the current draft.在P0012R1中,有一条注释:
In P0012R1, there is a comment that:
如何通过
std::function
传播"noexcept"是一个悬而未决的问题.It is an open issue how to propagate "noexcept" through
std::function
.我的猜测是,它们的意思是,如果强加了此附加要求,则不清楚如何实现
std::function
.希望其他人可以提供更多详细信息.My guess is that they mean that it is not clear how
std::function
could be implemented if this additional requirement were imposed. Hopefully, someone else can provide more details.这篇关于C ++ 17异常说明符类型系统将如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!