Is it possible to refer to std :: function <void (Args ...)> by standard?
All citations from N3797 .
4/3 [conv]
An expression e is possibly implicitly converted to type T if and only if the declaration T t = e; well formed, for some invented time variable t
This means that the expression cannot be implicitly converted to void , since void t=e is illegal for all expressions e . This is even true if e is an expression of type void , for example void(3) .
Thus, an expression of type void cannot be implicitly converted to void .
This leads us to:
20.9.2 / 2 Requirements [func.require]
Define CALL (f, t1, t2, ..., tN, R) in the form of CALL (f, t1, t2, ..., tN) implicitly converted to p.
In short, INVOKE(f, t1, t2, ..., tN, R) never acts if R is void , since nothing (including void ) can be implicitly converted to void .
As a result of this, all std::function<void(Args...)> have the property !*this and therefore cannot be called as the only constructors that do not have !*this as a postcondition (or not to copy such a state from another function that same type) require Callable one of the parameters.
09/20/11/7 Class function template [Func.wrap.func]
Required: F must be CopyConstructible, e must be Confirm (20.9.11.2) for argument types ArgTypes and return type p, Copy constructor and destructor should not exclude exceptions.
09/20/11/2 Class template function [Func.wrap.func]
The called object e of type F is redeemable for the argument types ArgTypes and the return type is p if the expression Sion is CALL (f, declval () ..., R), considered as an invaluable operand (item 5), well-formed (20.9.2).
As shown above, for std::function<void(Args...)> there are no Callable expressions.
If somehow found std::function<void(Args...)> where it was found, operator() is called:
call [func.wrap.func.inv]
Effects: CALL (f, std :: forward (args) ..., R) (20.9.2), where e is the target ject (20.9.1) * this.
as INVOKE(f, std::forward<ArgTypes>(args)..., void) poorly 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 Krugler, this question should appear in the list of library defects after the following mailing :
The corresponding problem with the library has already been sent, but not but visible in the list of problems.
We hope that when this becomes visible, we will also get a final answer on whether it is possible to build std::function with a signature returning void , passing the called code with a returning signature of non-void ( Using `std :: function <void (.. .)> `to call the non-void function ).
Update: this was introduced as LWG 2420 , which was allowed with respect to the void return type with a special static_cast result of the void function being called. This means that the called non- void returned may be the target std::function<void(...)> . LWG2420 was applied as an amendment after publication to C ++ 14; Meanwhile, all the compilers that I know effectively apply this behavior as an extension in C ++ 11 mode.