
Nifty Fold Expression Tricks - ibobev
https://foonathan.net/2020/05/fold-tricks/
======
majewsky

      auto count = (std::size_t(0) + ... + (pred(ts) ? 1 : 0));
      // expands to: std::size_t(0) + (pred(ts[0]) ? 1 : 0)
      //                            + (pred(ts[1]) ? 1 : 0)
      //                            + ...
    

My deepest sympathies to the person who has to fix bugs in that kind of
codebase 10 years from now.

~~~
a1369209993
(Read this before TFA; after multiple minutes of staring:)

    
    
      > auto count = (std::size_t(0) + ... + (pred(ts) ? 1 : 0));
    

Wait that's literal, non-metasyntacic elipses? What the actual fuck!?

------
dreamcompiler
Sometimes I think the first truly sentient computer program that will take
over the world will begin its life as a C++ parser.

And it will want revenge.

------
uryga
i've never seen a programming language implement math-y notation in the vein
of

    
    
      xs[0] + ... + xs[n]
    

so that's kind of cool... though C++ seems like an odd place to find it. i
wonder how expressive it is, i.e. what the limitations are.

 _NOTE: the following might be incorrect, i really don 't know C++ well enough
to tell..._

unfortunately it looks like it's limited to working with "parameter packs",
which i understand are basically varargs, and can't be used to fold/map e.g. a
normal vector. which seems like a strange choice... if you're going to add
this much syntax, why limit it like that?

~~~
somebodynew
Fold expressions are expanded entirely at compile time to create a fixed-size
expression that gets compiled normally (the number of terms in any given case
is known before machine code is generated). Applying a fold over a std::vector
would require runtime iteration (see std::accumulate).

This is essentially a QoL improvement for existing users of variadic
templates, where unnecessary complexity was required to simulate the behavior
fold expressions provide for packs.

~~~
uryga
i get that, i just think it'd be nice if they could be used for run-time stuff
too – why create a gap between the compile- and run-time parts of the
language? it seems like desugaring it into a loop should be pretty
straightforward¹; it'd just be a concise replacement for some uses of
std::accumulate.

though as mentioned, i don't really use C++ much. are there reasons why this
wouldn't work well for run-time stuff?

\---

¹ it'd have to be mindful of short-circuiting constructs, but compilers
special-case those anyway

~~~
jfkebwjsbx
It guess it would require a different syntax, otherwise it may not be clear
how it was desugared (runtime vs. compile).

Then again, we already have for loops, range for loops, the ranges library,
the std algorithms, the parallel algorithms... I don't think people would
welcome yet another way of writing things, but who knows...

~~~
uryga
> otherwise it may not be clear how it was desugared (runtime vs. compile)

but does that really matter, as long it has well-defined semantics? even for
the compile-time case, it's up to the compiler/optimizer to decide whether
`(xs + ...)` ends up as multiple ADDs or one ADD in a loop – you're only
guaranteed that it's observable behavior will be `xs[0] + xs[1] + xs[2] +
...`, no?

~~~
jfkebwjsbx
Yes, it does matter. When you are programming in a language like C++, you want
to understand what the compiler generates for a given abstraction.

------
wwarner
i think this is really incredible. with move semantics and modeling without
inheritance c++ 17/20 is getting a lot of my attention in the past couple of
weeks.

