Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why the template version is chosen below by the compiler?

The template version is used by the compiler to calculate t = max(a, b) and max(t, c). Any quote from the Standard supporting this is welcome.

#include <iostream>

template <typename T>
inline T const& max (T const& a, T const& b)
{
    std::cout << "template" << '\n';
    return a < b ? b : a;
}

template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
    return max (max(a,b), c);
}

inline int const& max (int const& a, int const& b)
{
    std::cout << "non-template" << '\n';
    return a <b ? b : a;
}

int main()
{
    std::cout << max(3, 5, 7) << '\n';   
}

The code prints

template
template
7
like image 991
Alexander Avatar asked Apr 11 '14 00:04

Alexander


1 Answers

The definition of your non-template version of max() is not visible at the call-site, it's defined afterwards. Either move that function above the 3-argument max() or add a prototype above the call-site.

int const& max (int const& a, int const& b);

Now the non-template version is chosen in both cases.

Live example


As for why this is the case, I believe §3.4.1/1 [basic.lookup.unqual] holds the answer.

In all the cases listed in 3.4.1, the scopes are searched for a declaration in the order listed in each of the respective categories; name lookup ends as soon as a declaration is found for the name. If no declaration is found, the program is ill-formed.

Note that argument-dependent name lookup does not apply in your case since the arguments to max are int, and not a user defined type. Only unqualified name lookup applies, hence, as quoted above, the lookup stops when the first match (the function template version of max()) is found.

The last sentence in the quoted section also explains why if you comment out the function template version of max() your code will not compile.

like image 199
Praetorian Avatar answered Sep 28 '22 08:09

Praetorian