[SOLVED] How C++ expands multiple parameters packs simultaneously,

Issue

This Content is from Stack Overflow. Question asked by Vladislav Ihost

Having following functions f0, f1, f2 in C++14 code, which accepts arbitrary number of fixed-length arrays:

#include <functional>
template<typename... TS, size_t N> void f0( TS(&& ... args)[N] ) {}
template<typename T, size_t... NS> void f1( T(&& ... args)[NS] )  {}
template<typename... TS, size_t... NS> void f2( TS(&& ... args)[NS] )  {}
 
int main(){
    f0({1,2}, {3.0,4.0}, {true, false});
    f1({1,2,3}, {4,5}, {6});
    f2({1,2,3}, {4.0,5.0}, {true});
    return 0;
}

Function f0 accepts arrays with different types and fixed array length. Function f1 accepts arrays with fixed type and different array lengths. It’s clear how this works: C++ compiler deduces variable-length parameter pack in immediate context of template function instantiation, which is expanded in (&& ... args) expression.

Function f2 accepts arrays with different types and different array lengths, which produces two variable-length parameter packs, however there is only one ellipsis operator in pack expansion (&& ... args), but code compiles and works well.

So question is: what is general rule for expanding multiple parameter packs within single ellipsis operator? Obviously, at a minimum, they must be the same length, but what are the other requirements? Is there a precise definition that the n-th element of the first parameter packing should expand along with the n-th element of the second parameter packing?

Also, following code with explicit template argument provision does not compile: f2<int,float,bool,3,2,1>({1,2,3},{4.0f,5.0f},{true});. It would be interesting to know the reasons for this behaviour.



Solution

All packs appearing as part of one pack expansion (...) must have exactly the same length. Otherwise substitution fails (which depending on context is a hard error or SFINAE). (see [temp.variadic]/7)

All packs are expanded so that the i-th expanded element of the pack expansion uses the i-th element of each pack. For the detailed expansion rule see [temp.variadic]/8.

(Links are to the post-C++20 draft of the standard, but the same applies to C++14.)


This Question was asked in StackOverflow by Vladislav Ihost and Answered by user17732522 It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?