Anatomy of a pretty printed motorcade

The std :: tuple print solution has recently been published here . For the most part, I get what happens. I am having trouble understanding what is going on in the print_tuple function.

template<class Ch, class Tr, class Tuple, std::size_t... Is> void print_tuple(std::basic_ostream<Ch,Tr>& os, Tuple const& t, seq<Is...>){ using swallow = int[]; (void)swallow{0, (void(os << (Is == 0? "" : ", ") << std::get<Is>(t)), 0)...}; } 

I do not understand what is happening in the body of this function. As far as I can tell, this has something to do with unpacking Is . I get the condition Is == 0 check if we are in the main element.

So what is going on?

+5
source share
2 answers

Skip the random set example, say:

 using Tuple = tuple<char, int, string>; 

Thus, the whole sequence with which our function will be called is:

 seq<0, 1, 2> 

And our package extension in the body:

 (void)swallow{0, (void(os << (Is == 0? "" : ", ") << std::get<Is>(t)), 0)...}; 

which, if we manually expand it as the compiler will be, will become:

 (void)swallow{0, (void(os << (0 == 0? "" : ", ") << std::get<0>(t)), 0), (void(os << (1 == 0? "" : ", ") << std::get<1>(t)), 0), (void(os << (2 == 0? "" : ", ") << std::get<2>(t)), 0) }; 

And then evaluating the branches:

 (void)swallow{0, (void(os << "" << std::get<0>(t)), 0), (void(os << ", " << std::get<1>(t)), 0), (void(os << ", " << std::get<2>(t)), 0) }; 

In other words, we are building an integer array of 4 0 s, with the side effect of printing the contents of the tuple, separated by a comma, making sure that we do not start with an extra comma, Four expressions must be evaluated in order to ensure that the contents of the tuple will be printed in order.

The initial (void) cast is only there to avoid warning an unused variable that compilers should emit if you have all the warnings. The initial 0 in array initialization handles the case when the tuple is empty.

+9
source

(os << (Is == 0? "" : ", ") << std::get<Is>(t)) print the Is th element (with the prefix ", " for Is > 0 )

Then, casting the result to void , to avoid the possible overload of the comma operator.

(/*previous stuff*/, 0)... makes series 0

{0, /*previous stuff*/ } handles cases when sizeof...(Is) == 0

swallow /*previous stuff*/ build an array int 0 .

void /*previous stuff*/ : cast to void to avoid warning.

+1
source

Source: https://habr.com/ru/post/1208164/


All Articles