4

The following code prints "First". Why the 1st template is selected, while the the 2nd one seems to be more specialized and should be a better match? (I use MSVC10)

I understand that it's somehow related to the fact that the second template accepts its argument by const &, but still can't realize why this make it a worse match.

#include <map>
#include <iostream>

template<class Range>
void go(Range &r)
{
  std::cout << "First" << std::endl;
}

template<class K, class V>
void go(const std::map<K, V> &m)
{
  std::cout << "Second" << std::endl;
}


int main()
{
  std::map<int, int> m;
  go(m);
}
Igor R.
  • 14,716
  • 2
  • 49
  • 83

1 Answers1

13

The compiler instantiates the first template to

void go(std::map<int, int>& r)

and the second to

void go(const std::map<int, int>& m)

The conversion sequence for the first is an identity conversion: nothing needs to be done, the lvalue argument binds directly to the reference.

The conversion sequence for the second is a qualifier conversion: the lvalue argument needs const added to bind to the reference.

So the first is a better match. If the variable in main was const to begin with, the second would be a better match, as you can see here, because then the two templates instantiate to the same thing and only then does the concept of "more specialized" come into play.

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
  • So, the instantiation goes before the overload resolution? Lets remove `const` from the 2nd example. According to your explanation, we'd get ambiguity here. But we don't. – Igor R. Jul 23 '13 at 14:43
  • 1
    @Igor: If two template instantiations are ambiguous, then the compiler looks at who's *more specialized*. If neither is, the ambiguity results in an error. – Xeo Jul 23 '13 at 15:06