Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function template overload resolution using const references

I am trying to understand the overload resolution rules in the following case:

template<typename T>
void f(const T& x) { 
    std::cout << __PRETTY_FUNCTION__ << std::endl; //-
}

template<typename T>
void f(T& x) { // <> Überladung Variante 2
    std::cout << __PRETTY_FUNCTION__ << std::endl; //-
}

int main()
{
    int e1 = 0;
    f(e1);

    const int e2 = 0;
    f(e2); 
}

The output is:

void f(T &) [T = int]
void f(const T &) [T = int]

As I understand in the first call to f(e1) leads to the viable functions

void f(const int&)
void f(int&)

from which the first one is chosen because the const-qualification hasn't to be removed.

The second call to f(e2) leads to the type deductions / viable functions

void f(const int&); // T -> int from first template overload 
void f(const int&); // T -> const int from second overload

and the output shows that the first overload is choosen.

But why?

like image 261
wimalopaan Avatar asked Sep 01 '16 11:09

wimalopaan


1 Answers

When performing type deduction with references, the const-ness (more specifically CV-ness) is not removed. So in your case the compiler has 2 overloads to choose from:

void f(const T &)
void f(T &)

The compiler then performs "pattern matching" when choosing the overload for your const int e2 = 0; argument. The first const overload is a better match (more specialized), as the second one would require deducing T as const int, which adds something (i.e. const-ness).

The rules for template type deductions are not super straightforward, so if you want to learn all nitty-gritty details about templates, I highly recommend the book

C++ Templates: The Complete Guide by David Vandevoorde and Nicolai M. Josuttis.

It's pre C++11, but nevertheless it tells you everything you can think of.

PS: you must make a differentiation between instantiation and template type deduction. The type deduction happens first, then an instantiation follows. So in your case you don't have 2 ambiguous instantiations as you may have thought initially.

like image 196
vsoftco Avatar answered Sep 29 '22 07:09

vsoftco