C++ template functions priority -


#include <iostream>  template <class u, class t> void foo(u&, t&) {     std::cout << "first"; }  template <class t> void foo(int&, const t&) {     std::cout << "second"; }  int main() {     int a;     double g = 2.;     foo(a, g); // prints "first"      return 0; } 

to call second foo overload, compiler needs perform 1 template type deduction, first overload, needs perform two. can please explain why first overload called?

overload resolution done in multiple steps.

first, through name lookup, select list of viable candidates. in case, is:

template <class u, class t> void foo(u&, t&);            // u = int, t = double  template <class t> void foo(int&, const t&)     // t = double 

next, determine conversion sequence necessary each argument each viable candidate. [over.ics.rank]:

standard conversion sequence s1 better conversion sequence standard conversion sequence s2 if [...]

  • s1 proper subsequence of s2 (comparing conversion sequences in canonical form defined 13.3.3.1.1, excluding lvalue transformation; identity conversion sequence considered subsequence of non-identity conversion sequence) or, if not that,
  • the rank of s1 better rank of s2, or s1 , s2 have same rank , distinguishable rules in paragraph below, or, if not that,

for first call, conversion sequence (identity, identity). second call, conversion sequence (identity, identity). we're equal there. neither of bullet points distinguish 2 calls. move on.

  • s1 , s2 reference bindings (8.5.3) , neither refers implicit object parameter of non-static member function declared without ref-qualifier, , s1 binds rvalue reference rvalue , s2 binds lvalue reference.

irrelevant.

  • s1 , s2 reference bindings (8.5.3) , s1 binds lvalue reference function lvalue , s2 binds rvalue reference function lvalue.

nope.

  • s1 , s2 differ in qualification conversion , yield similar types t1 , t2 (4.4), respectively, , cv-qualification signature of type t1 proper subset of cv-qualification signature of type t2.

qualification conversion pointer thing, nope.

  • s1 , s2 reference bindings (8.5.3), , types references refer same type except top-level cv-qualifiers, , type reference initialized s2 refers more cv-qualified type reference initialized s1 refers.

in case, first overload takes second argument double& while second overload takes const double&. former less cv-qualified latter, stop here - preferring foo(u&,t&).

only after steps determine conversion sequence better step more specialized template preferred. full rule ordering in [over.match.best] is:

given these definitions, viable function f1 defined better function viable function f2 if arguments i, icsi(f1) not worse conversion sequence icsi(f2), , then

  • for argument j, icsj(f1) better conversion sequence icsj(f2), or, if not that,

that's went through.

  • the context initialization user-defined conversion [ ... ]
  • the context initialization conversion function direct reference binding [ ... ]
  • f1 not function template specialization , f2 function template specialization, or, if not that,
  • f1 , f2 function template specializations, , function template f1 more specialized template f2 according partial ordering rules described in 14.5.6.2.

that's why pick foo(u&, t&). if remove const, however, both conversion sequences identical across steps - @ point, more specialized template (foo(int&, t&)) win.

note more specialized very last mechanism determine best candidate. it's final of tie breakers.

also note number of template deductions irrelevant. may matter in selecting between overload template , overload not template - not matter in selecting between overload has x template parameters , overload has y > x template parameters.


Comments

Popular posts from this blog

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

android - CollapsingToolbarLayout: position the ExpandedText programmatically -

Listeners to visualise results of load test in JMeter -