0

Sorry for being vague with my question, but I just don't understand what does this function does and how. Code from here:

template<typename ... T> auto sum (T ... t) { typename std::common_type<T...>::type result{}; //zero-initialization? (void)std::initializer_list<int>{(result += t, 0)...}; //why 0 is here return result; } 

I don't know why but this piece of code seems so odd, it don't look like C++ to me. Semantically, this function sums all the parameters in a result variable, obviously. But I completely do not understand why it was written that way. Using initializer_list here seem like a trick to trigger iteration over arguments in parameter pack but still...

Why initializer_list is explicitly was cast to void? To not take up extra memory?

And how iteration over parameter pack is going? Why not for example (void)std::initializer_list<int>{(result += t)...}; (it does not compile by the way).

3
  • 2
    This trick was common before fold expressions were invented in C++17. Nowadays, you can just write return (... + t); Before that, pack expansion could only appear in certain contexts, e.g. in a brace-init list. So to perform calculations over a pack, you arranged a dummy brace-init list where each initializer had a side effect you wanted. The value of the initializer doesn't matter, only its side effect. (result += t, 0) uses a comma operator - it says "evaluate result += t, then produce integer 0 as the value". Commented Dec 20, 2021 at 14:33
  • 2
    cast to void was to avoid warning for some compilers for unused expression. Commented Dec 20, 2021 at 14:38
  • std::initializer_list<int>{(result += t)...}; doesn't compile presumably because (result += t) is not of type int or convertible to int. In contrast, the type of (result += t, 0) is always the type of 0, which is int. Commented Dec 20, 2021 at 14:41

1 Answer 1

0

Thanks to the comments, I figured out the answer.

I haven't ever come across comma operator, so the line (result += t, 0) made to me no sense until your comments about EXISTENCE of comma operator and this question. So basically we initializing our list with zeros. And since I made type of initializer_list for integers, I can't write (void)std::initializer_list<int>{result += t...}, since returning value of result += t is int& not int.

So why don't we write (void)std::initializer_list<int&>{result += t...}? It doesn't compile, and I suspect that because array of references is forbidden in C++. So here's the solution to my problem:

template <typename ... T> auto sum1(T ... t) { std::common_type_t<T...> tmp{}; std::initializer_list<std::reference_wrapper<std::common_type_t<T...>>>{tmp += t...}; return tmp; } 
Sign up to request clarification or add additional context in comments.

1 Comment

"I can't write ... since returning value of result += t is int& not int" no, you can write that, at least if the result is of type int. "So here's the solution to my problem" Solution to what problem? Doesn't the code in the question work?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.