Implicit conversion to void

141 views
Skip to first unread message

Edward Catmur

unread,
Jul 17, 2014, 9:19:52 AM7/17/14
to std-dis...@isocpp.org
Consider:

void f();
std
::function<void()>{f};

The constructor of function requires a Callable argument ([func.wrap.func.con] paragraph 8) i.e. one for which INVOKE(f, void) is well-formed ([func.wrap.func] paragraph 2). INVOKE with a return type R performs implicit conversion to get from the return value of its callable to R ([func.require] paragraph 2). However "an expression e can be implicitly converted to a type T if and only if the declaration T t=e; is well-formed" ([conv] paragraph 3).

The declaration void t = f(); is clearly not well-formed, so this code is invalid.

Do we need to change the definition of implicit conversion to allow any expression to be implicitly converted to cv void, or would it be better to just special-case INVOKE(..., cv void)?

Note that static_cast<void> has a similar problem ([expr.static.cast] paragraph 4); this is seemingly contradicted by following paragraph 6: "Any expression can be explicitly converted to type cv void [...]".

Daniel Krügler

unread,
Jul 17, 2014, 9:33:37 AM7/17/14
to std-dis...@isocpp.org
A corresponding library issue has already been submitted, but is not
yet visible in the issue list.

- Daniel

Richard Smith

unread,
Jul 17, 2014, 5:19:53 PM7/17/14
to std-dis...@isocpp.org
On Thu, Jul 17, 2014 at 6:19 AM, Edward Catmur <e...@catmur.co.uk> wrote:
Consider:

void f();
std
::function<void()>{f};

The constructor of function requires a Callable argument ([func.wrap.func.con] paragraph 8) i.e. one for which INVOKE(f, void) is well-formed ([func.wrap.func] paragraph 2). INVOKE with a return type R performs implicit conversion to get from the return value of its callable to R ([func.require] paragraph 2). However "an expression e can be implicitly converted to a type T if and only if the declaration T t=e; is well-formed" ([conv] paragraph 3).

The declaration void t = f(); is clearly not well-formed, so this code is invalid.

Do we need to change the definition of implicit conversion to allow any expression to be implicitly converted to cv void, or would it be better to just special-case INVOKE(..., cv void)?

Generally, I would think that we should say that INVOKE with a return type R is valid if

  R f() { return c; }

is valid, where c is a call to its callable argument, or something equivalent to that. I don't think changing the core notion of 'implicitly converted' is the right approach.
 
Note that static_cast<void> has a similar problem ([expr.static.cast] paragraph 4); this is seemingly contradicted by following paragraph 6: "Any expression can be explicitly converted to type cv void [...]".

I don't think there's any actual contradiction here: p4 says you can static_cast<T>(e) if T t(e) is valid. p6 says, in addition to what p4 allows, you can also static_cast to cv void.

David Krauss

unread,
Jul 17, 2014, 6:55:10 PM7/17/14
to std-dis...@isocpp.org
On 2014–07–18, at 5:19 AM, Richard Smith <ric...@metafoo.co.uk> wrote:

Generally, I would think that we should say that INVOKE with a return type R is valid if

  R f() { return c; }

is valid, where c is a call to its callable argument, or something equivalent to that. I don't think changing the core notion of 'implicitly converted' is the right approach.

Not only that, but the library already has its own notion of “implicitly converted” which matches your example, in the is_convertible trait (N3936 §20.10.6/4). INVOKE might as well be defined in terms of the metaprogramming library?

Reply all
Reply to author
Forward
Message has been deleted
0 new messages