Consider this piece of C++11 code:
#include <iostream>
#include <cstddef>
template<typename T> void f(T, const char*) //#1
{
std::cout << "f(T, const char*)\n";
}
template<std::size_t N> void f(int, const char(&)[N]) //#2
{
std::cout << "f(int, const char (&)[N])\n";
}
int main()
{
f(7, "ab");
}
Alright, so... which overload is chosen? Before spilling the beans with compiler output, let's try to reason about this.
(All references to sections are for the final standard document for C++11, ISO/IEC 14882:2011.)
T
from #1 is deduced to int
, N
from #2 is deduced to 3
, both specializations are candidates, both are viable, so far so good. Which one is best?
First, the implicit conversions needed to match function arguments with function parameters are considered. For the first argument, no conversion is needed in either case (identity conversion), int
everywhere, so the two functions are equally good. For the second one, the argument type is const char[3]
, and the two conversions are:
- for #1, array-to-pointer conversion, category lvalue transformation, according to
[13.3.3.1.1]
; this conversion category is ignored when comparing conversion sequences according to[13.3.3.2]
, so this is basically the same as identity conversion for this purpose; - for #2, the parameter is of reference type and binds directly to the argument, so, according to
[13.3.3.1.4]
, this is again identity conversion.
Again, no luck: the two functions are still equally good. Both being template specializations, we now have to see which function template, if any, is more specialized ([14.5.6.2]
and [14.8.2.4]
).
EDIT 3: The description below is close, but not quite accurate. See my answer for what I believe to be the correct description of the process.
- Template argument deduction with #1 as parameter and #2 as argument: we invent a value
M
to substitute forN
,T
deduced asint
,const char*
as parameter can be initialized from an argument of typechar[M]
, everything's fine. As far as I can tell, #2 is at least as specialized as #1 for all types involved. - Template argument deduction with #2 as parameter and #1 as argument: we invent a type
U
to substitute forT
, a parameter of typeint
cannot be initialized from an argument of typeU
(unrelated types), a parameter of typechar[N]
cannot be initialized from an argument of typeconst char*
, and the value of the non-type parameterN
cannot be deduced from the arguments, so... everything fails. As far as I can tell, #1 is not at least as specialized as #2 for all types involved.
EDIT 1: The above has been edited based on comments from Columbo and dyp, to reflect the fact that references are removed before attempting template argument deduction in this case.
EDIT 2: Based on info from hvd, top level cv-qualifiers are also removed. In this case, it means const char[N]
becomes char[N]
, because cv-qualifiers on array elements apply to the array itself as well (an array of const
is also a const array
, so to speak); this wasn't obvious at all in the C++11 standard, but has been clarified for C++14.
Based on the above, I'd say partial ordering of function templates should choose #2 as more specialized, and the call should resolve to it with no ambiguity.
Now, back to the harsh reality. Both GCC 4.9.1 and Clang 3.5.0, with the following options
-Wall -Wextra -std=c++11 -pedantic
reject the call as ambiguous, with similar error messages. The error from Clang is:
prog.cc:16:2: error: call to 'f' is ambiguous
f(7, "ab");
^
prog.cc:4:27: note: candidate function [with T = int]
template<typename T> void f(T, const char*) //#1
^
prog.cc:9:30: note: candidate function [with N = 3]
template<std::size_t N> void f(int, const char(&)[N]) //#2
^
Visual C++ 2013's IntelliSense (based on the EDG compiler, as far as I know) also flags the call as ambiguous. Funnily enough, the VC++ compiler goes ahead and compiles the code with no errors, choosing #2. (Yay! It agrees with me, so it must be right.)
The obvious question for the experts is, why is the call ambiguous? What am I missing (in the partial ordering area, I would guess)?
const char*
andconst char[3]
are equally valid when binding to aconst char[3]
argument is no surprise. That's why we have to get to partial ordering of function templates to decide which overload to call. – bogdan[14.8.2.4]
says that, after the preliminary transformations, type deduction is done as described in[14.8.2.5]
, which is not how types are deduced from function calls, but rather deducing template arguments from a type. The rules in there don't allow for the same conversions as for function parameters; I guess they could be thought of as the same rules used for deducing class template parameters from the corresponding arguments. – bogdan