Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between variadic template and ellipsis?

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?

like image 317
Eduard Rostomyan Avatar asked May 22 '20 11:05

Eduard Rostomyan


1 Answers

What even is the first overload?

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.)

Why do we see that specific output?

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])

like image 196
AndyG Avatar answered Nov 09 '22 22:11

AndyG