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 or a 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 template g if, each pair of types used determine ordering, type f @ least specialized type g.
f more specialized g if f @ least specialized g , g not @ least specialized f.

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

Popular posts from this blog

How has firefox/gecko HTML+CSS rendering changed in version 38? -

javascript - Complex json ng-repeat -

jquery - Cloning of rows and columns from the old table into the new with colSpan and rowSpan -