C++ Variadic Templates for a General-Purpose and Fast Data Storage Container Builder

template< typename ... Args>
auto build_array(Args&&... args) -> std::array<typename std::common_
type<Args...>::type, sizeof...(args)>
{
    using commonType = typename std::common_type<Args...>::type;
    return {std::forward<commonType>(args)...};
}

int main()
{
    auto data = build_array(1, 0u, 'a', 3.2f, false);
    for(auto i: data)
    std::cout << i << " ";
    std::cout << std::endl;
}

Hey guys, I cannot understand the above code. So basically, the code is to write a function that takes any number of elements of any type, which can, in turn, be converted into a common type. The function should also return a container having all the elements converted into that common type, and it should also be fast to traverse. This is a books solution.

From what I understand <typename... Args> is to allow a variation of parameters. Then, (Args&&...args) also allows for a variety of parameters, but only rvalues? I do not understand the arrow notation and the rest of the function declaration. Like what is the difference between each of them. Additionally, the book also passes in ? for the templates such as, std::array<?,?>?

Finally, what does the return statement even mean (ending with an ellipsis?) ? and forward? Sorry, I am rambling on, but I just cannot make sense and obtain a detailed overview of what is going on. It would be really kind of you if you can elaborate on this?


but only rvalues?

When you see T&&,

  • if T is not a template parameter, then T&& means an rvalue reference to T, which can bind to rvalules only;
  • if T is a template parameter, then T&& means a forwarding/universal reference to T, which can bind to both rvalue and lvalues.

Therefore, in your case, since Args is a template parameter (precisely a type template parameter pack, number (2) here), Args&&... args expands to a comma separated sequence of function parameter declarations each of which as type a forwarding reference. For instance, if you pass 3 arguments to build_array, the deduction takes place as if you had a declaration like this:

template<typename Arg1, typname Arg2, typname Arg3>
auto build_array(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3)
    -> std::array<typename std::common_type<Arg1, Arg2, Arg3>::type, 3>

what does the return statement even mean (ending with an ellipsis?) ?

Again, ... is to expand some variadic thing in a comma separated sequence of things. So if args in

return {std::forward<commonType>(args)...};

is actually 3 things, then that statement is expanded to

return {std::forward<commonType>(arg1), std::forward<commonType>(arg2), std::forward<commonType>(arg3)};

Notice the position of the ellipsis. f(args)... is expanded to f(arg1), f(arg2), f(arg3), …, whereas f(args...) would be expanded to f(arg1, arg2, arg3, …).

and forward?

That's probably the less easy to understand bit, and would require a dedicated question. However many questions on that topic exist already, so you just have to search for them, rather than asking a new one. Here an answer of mine where I've most clearly explained the difference between std::move and std::forward. If you set understanding that answer of mine as your target, you'll understand std::forward (and std::move) and everything will be clearer.

I do not understand the arrow notation and the rest of the function declaration.

Essentially,

auto f(/* parameters */) -> SomeType

is equivalent to

SomeType f(/* parameters */)

with the advantage that in the former SomeType can refer to types that are in /* parameters */, if needed. In your case the return type makes use of Args.

the book also passes in ? for the templates such as, std::array<?,?>?

Probably the book is just trying to guide you through argument deduction, and it's using ? to mean "we don't know yet what it is; keep reading".