调用std :: function< void(Args ...)>下标准? [英] Is it illegal to invoke a std::function<void(Args...)> under the standard?
问题描述
所有报价均来自 N3797 。
4/3 [conv]
表达式
e
可以是
将
隐式转换为类型
T
如果且仅当声明为
T t = e;
是合格的,
是一些发明的临时变量
t
隐式转换为 void
,因为 void t = e
对所有表达式都是非法的 / code>。如果
e
是类型 void
的表达式,例如 void )
。
因此,类型 void
的表达式不能隐式转换为 void
。
这导致我们:
20.9.2 / 2要求[func.require]
定义
INVOKE
,t1,t2,...,tN,R)
as
INVOKE
(f,t1,t2,...,tN)
隐式转换为
R
。
简而言之, INVOKE(f,t1,t2,... ,
为
void
,则无效(包括 void
)可以隐式转换为 void
。
因此,所有 std :: function< void(Args ...)>
都有属性!* this
因此不能被调用,作为唯一的构造函数没有!* this
作为后置条件(或不复制这样的状态从另一个 function
of the same type)require Callable
的参数之一。
20.9.11.2/7类模板
function
[func.wrap.func]
需要:
F
应为
CopyConstructible
。
f
对于参数类型为callable(
20.9.11.2
)
ArgTypes
和返回类型
R
。
A
的复制构造函数和析构函数不会抛出异常。
20.9.11.2/ 2类模板
function
[func.wrap.func]
一个可调用对象
f
类型
F
是
可调用
用于参数类型
ArgTypes
和返回类型
R $ b b如果expres-
sion
INVOKE
(f,declat()...,R)
,被认为是未求值的操作数(条款
5
),很好
形成(
20.9.2
)。
上面,对于 std :: function< void(Args ...)>
没有 Callable
/ p>
如果发现这样的 std :: function< void(Args ...)>
code> operator()将会生成:
调用[func.wrap.func.inv] strong>
效果:
INVOKE
(f,std :: forward(args)...,R )
(
20.9.2
),其中
f
是目标ob-
项目(
20.9.1
)of
* this
。
为 INVOKE(f,std :: forward< ArgTypes>(args)...,void)
对所有参数和 f
不成立。
这行推理是否有效?
我得到了相同的结论,这里
根据Daniel Kruegler的说法,此问题应在下次邮寄之后出现在库缺陷列表中:
相应的库问题已经提交,但不是
在问题列表中可见。
希望一旦变得可见,我们也会得出一个结论性的答案,即是否允许构造一个 std :: function
带签名返回 void
传递带有签名的callable返回非void(使用`std :: function< void(...)>`调用非void函数) p>
更新:输入为 LWG 2420 ,该问题得到解决,支持特殊框架 void
return键入 static_cast
调用函数的结果为 void
。这意味着一个可调用的返回非 - void
可以是 std :: function< void(...)>
。 LWG2420作为出版后校正应用于C ++ 14;同时,我知道所有编译器有效地应用此行为作为C ++ 11模式中的扩展。
All quotes are from N3797.
4/3 [conv]
An expression e can be implicitly converted to a type T if and only if the declaration T t=e; is well-formed, for some invented temporary variable t
This implies no expression can be implicitly converted to void
, as void t=e
is illegal for all expressions e
. This is even true if e
is an expression of type void
, such as void(3)
.
So an expression of type void
cannot be implicitly converted to void
.
Which leads us to:
20.9.2/2 Requirements [func.require]
Define INVOKE (f, t1, t2, ..., tN, R) as INVOKE (f, t1, t2, ..., tN) implicitly converted to R .
In short, INVOKE(f, t1, t2, ..., tN, R)
is never valid when R
is void
, as nothing (including void
) can be implicitly converted to void
.
As a result of this, all std::function<void(Args...)>
have the property !*this
and thus cannot be called, as the only constructors that do not have !*this
as a postcondition (or do not copy such state from another function
of the same type) require Callable
of one of the parameters.
20.9.11.2/7 Class template function [func.wrap.func]
Requires: F shall be CopyConstructible . f shall be Callable ( 20.9.11.2 ) for argument types ArgTypes and return type R . The copy constructor and destructor of A shall not throw exceptions.
20.9.11.2/2 Class template function [func.wrap.func]
A callable object f of type F is Callable for argument types ArgTypes and return type R if the expres- sion INVOKE (f, declval()..., R) , considered as an unevaluated operand (Clause 5 ), is well formed ( 20.9.2 ).
As demonstrated above, there are no Callable
expressions for std::function<void(Args...)>
.
If somehow such a std::function<void(Args...)>
where found, invoking operator()
would be ill formed:
invocation [func.wrap.func.inv]
Effects: INVOKE (f, std::forward(args)..., R) ( 20.9.2 ), where f is the target ob- ject ( 20.9.1 ) of *this .
as INVOKE(f, std::forward<ArgTypes>(args)..., void)
is ill formed for all arguments and f
.
Is this line of reasoning sound?
Yes, your analysis is correct; I came to the same conclusion here.
According to Daniel Kruegler, this issue should appear on the library defect list subsequent to the next mailing:
A corresponding library issue has already been submitted, but is not yet visible in the issue list.
Hopefully once that becomes visible we'll also have a conclusive answer to whether it is allowable to construct a std::function
with signature returning void
passing a callable with signature returning non-void (Using `std::function<void(...)>` to call non-void function).
Update: this was entered as LWG 2420, which was resolved in favor of special-casing void
return type to static_cast
the result of the invoked function to void
. This means that a callable returning non-void
can be the target of a std::function<void(...)>
. LWG2420 was applied as a post-publication correction to C++14; meanwhile, all compilers I'm aware of effectively apply this behavior as an extension in C++11 mode.
这篇关于调用std :: function< void(Args ...)>下标准?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!