CWG Issue 495 (original) (raw)
This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 118e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2025-11-05
495. Overload resolution with template and non-template conversion functions
Section: 12.2.4 [over.match.best]Status: CD2Submitter: Nathan SidwellDate: 20 Dec 2004
[Voted into WP at July, 2009 meeting.]
The overload resolution rules for ranking a template against a non-template function differ for conversion functions in a surprising way. 12.2.4 [over.match.best] lists four checks, the last three concern this report. For the non-conversion operator case, checks 2 and 3 are applicable, whereas for the conversion operator case checks 3 and 4 are applicable. Checks 2 and 4 concern the ranking of argument and return value conversion sequences respectively. Check 3 concerns only the templatedness of the functions being ranked, and will prefer a non-template to a template. Notice that this check happens after argument conversion sequence ranking, but before return value conversion sequence ranking. This has the effect of always selecting a non-template conversion operator, as the following example shows:
struct C
{
inline operator int () { return 1; }
template <class T> inline operator T () { return 0; }
};
inline long f (long x) { return x; }
int
main (int argc, char *argv[])
{
return f (C ());
}The non-templated C::operator int function will be selected, rather than the apparently betterC::operator long instantiation. This is a surprise, and resulted in a bug report where the user expected the template to be selected. In addition some C++ compilers have implemented the overload ranking as if checks 3 and 4 were transposed.
Is this ordering accidental, or is there a rationale?
Notes from the April, 2005 meeting:
The CWG agreed that the template/non-template distinction should be the final tie-breaker.
Proposed resolution (March, 2007):
In the second bulleted list of 12.2.4 [over.match.best] paragraph 1, move the second and third bullets to the end of the list, to read as follows:
- for some argument j, ICS_j_(F1) is a better conversion sequence than ICS_j_(F2), or, if not that,
- the context is an initialization by user-defined conversion (see 9.5 [dcl.init], 12.2.2.6 [over.match.conv], and 12.2.2.7 [over.match.ref]) and the standard conversion sequence from the return type of F1 to the destination type (i.e., the type of the entity being initialized) is a better conversion sequence than the standard conversion sequence from the return type of F2 to the destination type, [Example: ... —_end example_] or, if not that,
- F1 is a non-template function and F2 is a function template specialization, or, if not that,
- F1 and F2 are function template specializations, and the function template for F1 is more specialized than the template for F2 according to the partial ordering rules described in 13.7.7.3 [temp.func.order].