Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does six dots mean in variadic templates? [duplicate]

While looking at this question I found myself in the cpp reference site where I noticed a strange and new to me syntax :

template<class Ret, class... Args> struct is_function<Ret(Args......)volatile &&> : std::true_type {}; 

Yep, 6 dots ! Initially I thought this was a typo, but after checking the libstdc++ source again there it was eg at line 444 :

template<typename _Res, typename... _ArgTypes> struct is_function<_Res(_ArgTypes......) volatile &&> : public true_type { }; 

Is this a valid syntax ? Dot dot dot, are used to pack and unpack parameter packs ? What do 6 dots do ?

like image 965
Lorah Attkins Avatar asked Dec 21 '14 23:12

Lorah Attkins


People also ask

What three dots mean in C++?

Ellipsis in C++ allows the function to accept an indeterminate number of arguments. It is also known as the variable argument list.

What are Variadic templates C++?

Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration. However, variadic templates help to overcome this issue.

What is Variadic function in C?

Variadic functions are functions that can take a variable number of arguments. In C programming, a variadic function adds flexibility to the program. It takes one fixed argument and then any number of arguments can be passed.

What is a parameter pack?

[edit] A template parameter pack is a template parameter that accepts zero or more template arguments (non-types, types, or templates). A function parameter pack is a function parameter that accepts zero or more function arguments. A template with at least one parameter pack is called a variadic template.


1 Answers

Why does libstdc++ use ... ... in it's implementation of is_function? If we check out the cppreference section for std::is_function it gives a sample 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 the second set of ... to match a variadic function like 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, we have functions like fprintf that two arguments before the variadic terms and we need to match those as well. Indeed if we use that implementation and attempt to match printf without the ... ... specialization then it fails see it live.

This corner of the language is covered in this post C++11's six dots:

I was mucking around the other day and discovered this nice little oddity:

template <typename... Args> void foo(Args......); 

As it turns out, ...... can be totally valid C++11. This is what happens when backward compatibility mixes with new hotness.

// These are all equivalent.

template <typename... Args> void foo1(Args......); template <typename... Args> void foo2(Args... ...); template <typename... Args> void foo3(Args..., ...); 

Hopefully the last one shows what is happening here. [...]

Why is this valild? We can see that , ... is synonymous with ... from the draft C++11 standard section 8.3.5 [dcl.fct] which has the following grammar:

parameter-declaration-clause:   parameter-declaration-listopt...opt   parameter-declaration-list , ... 

and says:

[...] Where syntactically correct and where “...” is not part of an abstract-declarator, “, ...” is synonymous with “...”. [...]

like image 154
Shafik Yaghmour Avatar answered Sep 25 '22 01:09

Shafik Yaghmour