Description
Full name of submitter: Janet Cobb
Reference (section label): [over.match.funcs]
Issue description:
Consider the following code:
struct S {
template<int = 0>
operator int&&() { throw 0; }
};
int i = S();
The four common compilers agree that this is well-formed.
Initialization is done pursuant to [dcl.init.general]/16.7. As far as I can tell, the only candidates are those defined by [over.match.funcs.general]/7. Since the object being initialized is of type int
, the first sentence only introduces candidates that would be found by operator int
, which does not include the conversion function template. The remainder of the paragraph explicitly excludes conversion function templates (regardless of the "permissible types"). Thus, there do not appear to be any candidates for the conversion.
Since all common implementations think operator int&&
is a candidate, I'm filing this defect report rather than a bug report with each implementation, in the hopes that this is an issue with the wording.
Here are some other interesting cases with templates that do not appear to be candidates under the current wording:
- All implementations agree that a candidate requiring function pointer conversion is found.
- All implementations agree that a candidate requiring derived-to-base conversion is not found.
- All implementations agree that a candidate requiring conversion from
std::nullptr_t
to a pointer type is not found. - All implementations agree that a candidate requiring conversion to `void* is not found.
- All implementations agree that a candidate requiring a qualification conversion introducing
const
is found. - There is implementation diverge on whether a candidate requiring qualification conversion from an array of known bound to an array of unknown bound is found.
Suggested resolution:
Exactly how this should be resolved is unclear. One possibility would be to modify the first sentence of [over.match.funcs.general]/7 to include cv T
, cv T&
, and cv T&&
just like the second portion of the paragraph does. This would address the initial example, but not any of the other cases that implementations think are well-formed.
This suggests that a potential resolution would be to explicitly include types U
that can be converted to T
by some specific subset of conversions (similarly to, e.g., [over.match.conv]. Another possible resolution is that the status quo is correct and that all of the implementations are wrong, although implementing that seems likely to break code and perhaps counterintuitive (since, to me at least, it seems like the original example should be well-formed).