Why libstdc++ use ... ... in the implementation of is_function ? If we check the cppreference section for std :: is_function , it gives an example implementation and says for the first case ... ... :
// specialization for variadic functions such as std::printf template<class Ret, class... Args> struct is_function<Ret(Args......)> : std::true_type {};
so we need a second set ... to match a function variable, such as printf :
Comma optional as per 8.3.5 [dcl.fct] | v Ret(Args... ...) ^ ^ | | Match a function with a variable number of arguments | and the function is a variadic function
Note that we have functions such as fprintf that have two arguments before variable members, and we also need to match them. Indeed, if we use this implementation and try to match printf without specialization ... ... then it fails to see it live .
This corner of the language is considered in this C ++ 11 post six points :
I pounced the other day and discovered this cute little weirdness:
template <typename... Args> void foo(Args......);
As it turned out, ...... C ++ 11 may be completely valid. This is what happens when backward compatibility mixes with the new heat.
// All are equivalent.
template <typename... Args> void foo1(Args......); template <typename... Args> void foo2(Args... ...); template <typename... Args> void foo3(Args..., ...);
I hope the latter shows what is happening here. [...]
Why is it wallill? We can see that , ... is a synonym ... from the standard section of the C ++ 11 8.3.5 project [dcl.fct], which has the following grammar:
parameter-declaration-clause: parameter-declaration-listopt...opt parameter-declaration-list , ...
and says:
[...] Where is syntactically correct and where "..." is not part of the abstract-declarator, ", ..." is synonymous with "...". [...]