调用std :: function< void(Args ...)>下标准? [英] Is it illegal to invoke a std::function<void(Args...)> under the standard?

查看:270
本文介绍了调用std :: function< void(Args ...)>下标准?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所有报价均来自 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&lt; void(Args ...)&gt;下标准?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆