Overload resolution with template and non-template conversion functions
12.2.4 [over.match.best]
Nathan Sidwell

Created on 2004-12-20.00:00:00 last changed 144 months ago


Date: 2009-07-15.00:00:00

[Voted into WP at July, 2009 meeting.]

Date: 2007-03-15.00:00:00

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, ICSj(F1) is a better conversion sequence than ICSj(F2), or, if not that,

  • the context is an initialization by user-defined conversion (see 9.4 [dcl.init], [over.match.conv], and [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 [temp.func.order].

Date: 2005-04-15.00:00:00

Notes from the April, 2005 meeting:

The CWG agreed that the template/non-template distinction should be the final tie-breaker.

Date: 2004-12-20.00:00:00

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; }

    main (int argc, char *argv[])
      return f (C ());

The non-templated C::operator int function will be selected, rather than the apparently better C::operator long<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?

Date User Action Args
2010-03-29 00:00:00adminsetstatus: wp -> cd2
2009-11-08 00:00:00adminsetstatus: dr -> wp
2009-08-03 00:00:00adminsetmessages: + msg2268
2009-08-03 00:00:00adminsetstatus: ready -> dr
2009-03-23 00:00:00adminsetstatus: review -> ready
2007-03-11 00:00:00adminsetmessages: + msg1466
2007-03-11 00:00:00adminsetstatus: drafting -> review
2005-05-01 00:00:00adminsetmessages: + msg1163
2005-05-01 00:00:00adminsetstatus: open -> drafting
2004-12-20 00:00:00admincreate