c++ - Overload resolution and partial template ordering -
consider simple pair of function templates.
template <typename t> void foo(t& ) { std::cout << __pretty_function__ << '\n'; } template <typename c> void foo(const c& ) { std::cout << __pretty_function__ << '\n'; }
if call foo
non-const argument:
int = 4; foo(i);
the t&
overload preferred based on [over.ics.rank]/3.2.6, since deduced reference int&
less cv-qualified deduced reference const int&
.
however, if call foo
const argument:
const int ci = 42; foo(ci);
the const c&
overload preferred because "more specialized" based on [over.match.best]/1.7. rules determine this? understanding synthesize type c
(call it, m
) , try perform deduction on foo(m)
- succeed (with t == m
). it's rvalue cause deduction fail - how compiler know has choose rvalue in synthesis step?
disclaimer: types consider types of parameters. types/value categories/etc. of actual arguments passed solely considered in overload resolution, never in partial ordering.
partial ordering considers both overloads in 2 "turns", in 1 template parameter template, , other template argument template. [temp.deduct.partial]/2:
for each of templates involved there original function type , transformed function type. [..] deduction process uses transformed type argument template , original type of other template parameter template. process done twice each type involved in partial ordering comparison: once using transformed template-1 argument template , template-2 parameter template , again using transformed template-2 argument template , template-1 parameter template.
you should familiar way transformed "templates" generated. specified in §14.5.6.2/3.
to produce transformed template, each type, non-type, or template template parameter (including template parameter packs (14.5.3) thereof) synthesize unique type, value, or class template respectively , substitute each occurrence of parameter in function type of template.
so our (transformed) argument templates
void foo( unique1& ); void foo( unique2 const& );
[temp.deduct.partial]/3 & /4:
the types used determine ordering depend on context in partial ordering done:
- in context of function call, types used function parameter types function call has arguments. [..]
each type nominated above parameter template , corresponding type argument template used types of
p
,a
.
thus have 2 turns, , in both have type p
, type a
:
turn 1:
p1
: t const&
a1
: unique1&
turn 2:
p2
: t&
a2
: unique2 const&
but before fun begins, transformations performed on these types - abbreviated [temp.deduct.partial]/5 & /7:
- if
p
ora
references, they're replaced type refer to. - any top-level cv-qualifiers removed.
note removed cv-qualifiers "remembered" later. [temp.deduct.partial]/6:
if both
p
,a
reference types (before being replaced type referred above), determine of 2 types (if any) more cv-qualified other; otherwise types considered equally cv-qualified partial ordering purposes. result of determination used below.
thus we're left
turn 1:
p1
: t
a1
: unique1
turn 2:
p2
: t
a2
: unique2
now perform deduction - succeeds in both turns setting t=unique[1/2]
. [temp.deduct.partial]/8:
if deduction succeeds given type, type argument template considered @ least specialized type parameter template.
that gives both unique1&
@ least specialized t const&
, , unique2 const&
@ least specialized t&
.
however, [temp.deduct.partial]/(9.2) steps in:
if, given type, deduction succeeds in both directions (i.e., types identical after transformations above) , both
p
,a
reference types (before being replaced type referred above):
[..]; otherwise,
if type argument template more cv-qualified type parameter template (as described above), parameter type not considered @ least specialized argument type.
the remembered cv-qualifiers come play. a2
"more cv-qualified (as described above)" p2
, hence p2
not considered @ least specialized a2
.
finally, [temp.deduct.partial]/10:
function template
f
@ least specialized function templateg
if, each pair of types used determine ordering, typef
@ least specialized typeg
.
f
more specializedg
iff
@ least specializedg
,g
not @ least specializedf
.
implies since type t&
not @ least specialized unique2 const&
, established t const&
@ least specialized unique1&
, t const&
-overload more specialized t&
-overload.
the aforementioned rule in paragraph 9 subject of cwg #2088 created 4 months ago r. smith:
the late tiebreakers lvalue-vs-rvalue references , cv-qualification in 14.8.2.4 [temp.deduct.partial] paragraph 9 applied
if, given type, deduction succeeds in both directions (i.e., types identical after transformations above) , both
p
,a
reference types (before being replaced type referred above):however, based on false assumption. [..] need decide whether rule “deduction succeeds in both directions” or “the types identical.” latter seems more reasonable.
this not alter result established though, since types got indeed identical.
Comments
Post a Comment