Reputation: 6556
I know the title does no make much of a sense, but the code will explain my problem.
template<typename T>
void foo(T...) {std::cout << 'A';}
template<typename... Ts>
void foo(Ts...) {std::cout << 'B';}
int main(){
foo(1);
foo(1,2);
}
Try to guess the output of this program before reading the continuation:
So the output is AB
Can anyone explain why for 1 argument function the priority is given to ellipsis, and for 2 argument to variadic template?
Upvotes: 21
Views: 2194
Reputation: 41145
Per [dcl.fct]
Where syntactically correct and where “...” is not part of an abstract-declarator, “, ...” is synonymous with “...”.
So this makes the first overload a variadic function (that also happens to be templated) that is equivalent to:
template<typename T>
void foo(T, ...) {std::cout << 'A';}
(N.B. The cppreference page contains an example with similar elision of the comma between the first argument and the variadic arguments.)
The compiler prefers the other overload when you pass two arguments because, during overload resolution, an ellipsis conversion sequence is always ranked dead last when ranking viable overloads. ([over.ics.rank])
The compiler prefers this first overload when a single argument is passed because simply, the ellipsis is not matched (because there is nothing to match). This prevents the function from being considered as an ellipsis conversion sequence. Normal function template ranking then happens and it is determined that this function is more specialized than the variadic one ([temp.deduct.partial])
Upvotes: 16
Reputation: 218098
Following overload_resolution#Best_viable_function
For f(1)
,
We go though 5)
or, if not that, F1 and F2 are both template specializations and F1 is more specialized according to the partial ordering rules for template specializations
And from Function_template_overloading
After considering every P and A in both directions, if, for each type that was considered, [..]
In case of a tie, if one function template has a trailing parameter pack and the other does not, the one with the omitted parameter is considered to be more specialized than the one with the empty parameter pack.
So ellipsis function template<typename T> void foo(T,...)
is considered more specialized than variadic template<typename ...Ts> void foo(Ts...)
.
for f(1, 2)
Reading Ranking_of_implicit_conversion_sequences
In variadic version we have exact match, whereas ellipsis has ellipsis conversion sequence
So variadic is better match.
Upvotes: 5