back
15 comments

  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.
(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!?
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.

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?

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.

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

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...

> 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?

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.
Ellipsis being used for meta-programming expansion is decades old(used in scheme). Here is a reference: https://docs.racket-lang.org/reference/stx-patterns.html#%28...
thanks for pointing that out, completely forgot about lisps!
python has ellispes in the grammar set but I don't think it's used yet.

Also I'd bet a dollar that there are 100 lisp libs with this (published or not)

seems like it's actually a common thing in Scheme (linked in a sibling comment)
yes
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.