Question

In Section 2.4 Overloading Function Templates of the book "C++ Templates - The Complete Guide" you'll find the following example:

// maximum of two int values
inline int const& max (int const& a, int const& b)
{
    return a < b ? b : a;
}
// maximum of two values of any type
template <typename T>
inline T const& max (T const& a, T const& b)
{
    return a < b ? b : a;
}
// maximum of three values of any type
template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
    return max (max(a,b), c);
}
int main()
{
    ::max(7, 42); // calls the nontemplate for two ints (1)
}

However in B.2 Simplified Overloading Resolution of Appendix B, the author states:

Note that overload resolution occurs after template Argument deduction, ... (2)

According to (2), ::max(7,42) should call max<int> by argument deduction.

Was it helpful?

Solution 3

After template argument deduction overload resolution occurs between

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

and

2) template <>
   inline int const& max (int const& a, int const& b)

In this situation 1) is called as specified in C++ standard 13.3.3 par. 1 (Draft n3092).

Msdn also clearly states it:

If a nontemplate function is an equally good match to a template function, the nontemplate function is chosen

http://msdn.microsoft.com/en-us/library/s016dfe8%28v=vs.80%29.aspx

OTHER TIPS

The compiler will prefer non template function in overload resolution if the functions are both an exact match, including cv qualifiers.

Therefore the non template will be picked here, even though the templated function essentially comes to the same.

EDIT:

In standard draft N3485 I have found this:

13.3.3 Best viable function [over.match.best]

Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then

...

F1 is a non-template function and F2 is a function template specialization, or, if not that,

— F1 and F2 are function template specializations, and the function template for F1 is more specialized than the template for F2 according to the partial ordering rules described in 14.5.6.2.

...

According to (2), ::max(7,42) should call max<int> by argument deduction.

No. Think about it, to do overload resolution (aka, to pick the best match), the compiler first needs to know all available overloads and be able to compare them. Note how a function template by itself is not a valid function, it first needs to be instantiated to create a real function.

This means that first, the compiler looks after all function templates named max, tries template argument deduction for every one of them, and then does overload resolution on the instantiated functions together with the non-template functions.

Here's a visualization of the functions (leaving out cv-qualifiers for brevity):

                    int max(int, int);
template<class Arg> Arg max(Arg, Arg);
template<class Arg> Arg max(Arg, Arg, Arg);

Let's walk through the invokation ::max(7, 42).

First, the compiler sees that there are three candidate functions. However, it can't just compare the first overload of max to the other two - that'd be like comparing apples and oranges. Instead, it first needs to "stamp out" a real function from the function template blue-prints. This happens, in our case, through template argument deduction:

int max(int, int); // originally non-template
int max(int, int); // originally template
int max(int, int, int); // not enough arguments, invalid

With the third overload being thrown out thanks to mismatching argument / parameter counts, we're down to two. From a perspective of overload resolution, both are equal - but wait! Now a certain rule steps in that says:

§13.3.3 [over.match.best] p1

[...] Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if [...]:

  • F1 is a non-template function and F2 is a function template specialization,

Per Paragraph 13.3.3/1 ("Best Viable Function" in the context of overload resolution) of the C++11 Standard:

Define ICSi(F) as follows:

— if F is a static member function, ICS1 (F) is defined such that ICS1 (F) is neither better nor worse than ICS1 (G) for any function G, and, symmetrically, ICS1 (G) is neither better nor worse than ICS1 (F)132; otherwise,

— let ICSi(F) denote the implicit conversion sequence that converts the i-th argument in the list to the type of the i-th parameter of viable function F. 13.3.3.1 defines the implicit conversion sequences and 13.3.3.2 defines what it means for one implicit conversion sequence to be a better conversion sequence or worse conversion sequence than another.

Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then

— for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2), or, if not that,

— the context is an initialization by user-defined conversion (see 8.5, 13.3.1.5, and 13.3.1.6) and the standard conversion sequence from the return type of F1 to the destination type (i.e., the type of the entity being initialized) is a better conversion sequence than the standard conversion sequence from the return type of F2 to the destination type. [...]

F1 is a non-template function and F2 is a function template specialization, or, if not that,

— F1 and F2 are function template specializations, and the function template for F1 is more specialized than the template for F2 according to the partial ordering rules described in 14.5.6.2.

This means that in the context of overload resolution, when a function generated by instantiating a function template (therefore, after type deduction) is an equally good match as a non-template function, the non-template function is preferred.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top