[HN Gopher] C++26: The Oxford Variadic Comma
___________________________________________________________________
C++26: The Oxford Variadic Comma
Author : ingve
Score : 92 points
Date : 2026-03-11 07:27 UTC (4 days ago)
(HTM) web link (www.sandordargo.com)
(TXT) w3m dump (www.sandordargo.com)
| mFixman wrote:
| I used to slay with this in code golfing competitions from
| TopCoder, where you had to implement a function to solve a
| particular problem, thanks to C pointer maths and the gcc
| generally putting function arguments in order in the stack.
|
| Turns out, these two are equivalent in practice (but UB in the
| C++ standard): double solve(double a, double b,
| double c, double d) { return a + b + c + d; }
| double solve(double a ...) { return a + 1[&a] + 2[&a] +
| 3[&a]; }
| camel-cdr wrote:
| K&R syntax is -1 char, if you are in C:
| double solve(double a,double b,double c,double d){return
| a+b+c+d;} double solve(double a...){return
| a+1[&a]+2[&a]+3[&a];} double solve(a,b,c,d)double
| a,c,b,d;{return a+b+c+d;}
| mananaysiempre wrote:
| > Turns out, these two are equivalent in practice
|
| Not in the x86-64 SysV ABI they aren't. The arguments will be
| passed in registers (yes, even the variadic ones), so how your
| compiler will interpret 1[&a] is anybody's guess. (For me,
| x86_64-unknown-linux-gnu-g++ -O2 yields, essentially, return
| a+a+a+a; which is certainly an interpretation. I'm also getting
| strange results from i686-unknown-linux-gnu-g++ -O2, but my x87
| assembly is rusty enough that I don't really get what's going
| on there.)
| Sharlin wrote:
| > return a+a+a+a; which is certainly an interpretation.
|
| Zero is the only valid index of &a, so I presume the compiler
| just assumes that all the indexes in 1[&a] + 2[&a] etc must
| be zero. Even though they're in this case compile-time
| constants - the optimizer could check but why bother given
| that it's UB anyway. I assume modern C/C++ compilers have
| some flag to diagnose indexing that's known to be OOB at
| compile time.
| mananaysiempre wrote:
| I'm so used to sticking -Wall in my compilation flags the
| moment I write a build script that I didn't realize it
| wasn't there for this quick experiment. Yes, thank you,
| there are indeed diagnostics once you ask for them:
| test.cpp: In function 'double solve(double, ...)':
| test.cpp:4:20: warning: array subscript 1 is outside array
| bounds of 'double [1]' [-Warray-bounds=] 4 |
| return a + 1[&a] + 2[&a] + 3[&a]; |
| ~~~~^ test.cpp:3:58: note: at offset 8 into object
| 'a' of size 8 3 | extern "C"
| __attribute__((noinline)) double solve(double a, ...) {
| |
| ~~~~~~~^ [repeat twice more for the other two
| accesses]
| Joker_vD wrote:
| double solve(double a[]) { return 0[a] + 1[a] + 2[a]
| + 3[a]; } solve((double[]){1, 2, 3, 4});
|
| The cast in the invocation can be macro-ed away. And the best
| thing is, the actual stack layout and data movement/shuffling
| is pretty much identical to the approach with <stdargs.h>, and
| with no UB or compiler intrinsics.
| kevin_thibedeau wrote:
| That's a compound literal, not a cast.
| advael wrote:
| This seems pretty good to me just on the level of trying to read
| C as someone using C++. Parameter packs and variadic templates
| are easily the most confusing syntax in C++ and cleaning it up
| is... very welcome
| jkaplowitz wrote:
| Hats off for using "..." in your comment immediately after a
| valid identifier word and with no comma in between, given the
| topic of the article.
| advael wrote:
| Hats off for noticing. Not to be taken for granted in an
| increasingly skimming-oriented world
| PaulDavisThe1st wrote:
| There remains the problem of defining what the meaning of
| ...is, is.
| lasgawe wrote:
| learned something new. thanks for the article.
| throwaway2027 wrote:
| C++ got too complicated after C++23 I went back to C.
| Conscat wrote:
| No offense intended to your perspective, but I do find it a
| little amusing that C++23, which was generally considered a
| disappointingly small update due to COVID complications, was
| the breaking point in complexity.
| FartyMcFarter wrote:
| You can always restrict yourself to a subset of C++ that takes
| advantage of RAII (resource handling is extremely painful in
| C), and get performance benefits like move semantics, without
| the insanely complex stuff.
|
| I love C, but C++ has worthwhile advantages even if you heavily
| restrict which features you use.
| jjgreen wrote:
| C is the new vinyl.
| staplung wrote:
| Of course since the old syntax is merely deprecated and not
| removed, going forward you now have to know the old, bad form and
| the new, good form in order to read code. Backwards compatibility
| is a strength but also a one-way complexity ratchet.
|
| At least they managed to kill `auto_ptr`.
| Conscat wrote:
| PyCuda 2024, used fairly often in certain industries, still
| contains `auto_ptr` ;-;
| hrmtst93837 wrote:
| If two template spellings trip you up, C++ is not your biggest
| problem. The joke is that each 'cleanup' sands off a tiny rough
| edge while the commitee leaves the old strata in place, so the
| language keeps accreting aliases and exceptions instead of
| dropping dead weight.
| tialaramex wrote:
| Several times now C++ enthusiasts and indeed the committee
| have been told the way forward is the "Subset of a superset"
| that is, Step 1. Add a few new things to C++ and then Step 2.
| Remove old things to make the smaller, better language they
| want.
|
| Once they've obtained permission to do Step 1 they can add
| whatever they want, and in a few years for them it's time to
| repeat "Subset of a superset" again and get permission for
| Step 1 again. There is no Step 2, it's embarrassing that this
| keeps working.
| vlovich123 wrote:
| I think Rust has shown a way to remove deprecated interfaces
| while retaining back compat - automated tooling to migrate to
| the next version and give a few versions for a deprecated
| interfaces to stick around at the source level.
| jjmarr wrote:
| C++ almost never removes features because of the ABI
| compatibility guarantees. Programs compiled with older
| versions of the standard can be linked against newer
| versions.
|
| This is allegedly because in the 80s companies would write
| software, fire the programmers, and throw the source code
| away once it compiled.
| Sharlin wrote:
| Fixing syntax by definition does not affect the ABI. And
| Rust has shown that both ABI and API compatibility can be
| achieved in the presence of several "versions" (editions)
| of the language in the same build.
| Karliss wrote:
| I doubt it will be a problem in practice.
|
| Regular variadic arguments in general aren't used very often in
| C++ with exception of printf like functions. Not rare enough
| for majority of C++ programmers to not know about them, but
| definitely much more rare than their use in python. Main reason
| people know about it at all is printf. The "new" C compatible
| form has been supported since the first ISO standardized
| version of c++ if not longer. There haven't been a good reason
| to use the "old" form for a very long time. Which means that
| the amount of C++ code using deprecated form is very low.
|
| Being deprecated means that most compilers and linters will
| likely add a warning/code fix suggestion. So any maintained
| project which was accidentally using C incompatible form will
| quickly fix it. No good reason not to.
|
| As for the projects which for some reason are targeting ancient
| pre ISO standard c++ version they wouldn't have upgraded to
| newer standard anyway. So if new standard removed old form
| completely it wouldn't have helped with those projects.
|
| So no you don't need to know the old form to read C++ code. And
| in the very unlikely case you encounter it, the way for
| accessing variadic arguments is the same for both forms through
| special va_list/va_arg calls. So if you only know the "new"
| form you should have a pretty good idea of whats going on
| there. You might lookup in references what's the deal with
| missing coma, but other than that it shouldn't be a major
| problem for reading code. This is hardly going to be the
| biggest obstacle when dealing with code bases that old.
| layer8 wrote:
| The "new" form has been valid since the original 1998 C++
| standard, where it was added for compatibility with C. The old
| pre-standard form was kept for backwards compatibility, and is
| only now being deprecated.
| zlfn wrote:
| C++ seems to be constantly getting complicated. If the major
| version were to change, there wouldn't be any need for backward
| compatibility with the existing code, and it would have been okay
| to delete that syntax while creating an automatic formatter.
| dnmc wrote:
| Are you suggesting we move to C++++?
| zlfn wrote:
| It's already there. It's called C#
| HackerThemAll wrote:
| Well, C# also has its quirks already. Like the crippled
| finalizers which are never to be used. If the IDisposable
| interface had been correctly designed, finalizers could
| become be the "public void Dispose(void)". Or the manual
| passing of Task in case of async methods, which is... kinda
| smelly.
| tialaramex wrote:
| It's possible you didn't realise, but C# is sometimes
| said to be named that way because # is the symbol you get
| if you draw ++ small and then on the line below ++ again.
| Hence C++++
|
| All languages have some spikier edges, there are no
| languages I know where I think "Well, even if we could
| start over I have no idea how to improve this". What's
| notable about C++ is just how rich that "could do better"
| seam is, so very many of their defaults are wrong, so
| many of their keywords are the wrong word, so many of
| their standard library features are allowed, sometimes
| even mandated to be crap.
| HackerThemAll wrote:
| I think you meant to get that to the original poster, who
| seems to imply C# is the flawless, bestest incarnation of
| C\\+\\+(\\+\\+)+.
| kstrauser wrote:
| I don't know if that's true or not, but while the thought
| never crossed my mind before your comment, it's now canon
| in my mind. Yes, C# is spelled C++++ with a ligature.
| Sharlin wrote:
| The name is actually pretty clever (the fact that it was
| originally un-googlable notwithstanding). There are at
| least three interpretations:
|
| * "C sharp" as in "C but higher",
|
| * C with four pluses, and
|
| * a homophone of "see sharp"
| cyberax wrote:
| This is a fundamental problem with GC-ed languages. You
| can't get predictable finalization, so IDisposable can
| never be implemented reliably.
| m-schuetz wrote:
| Personally I like C+. Picking the nice parts of C++, but
| skipping all the nonsense. I just wish C++ hadn't
| deliberately screwed up designated initializers with
| mandatory ordering. The C version of it that allows out-of-
| order assignments is clearly superior.
| dist-epoch wrote:
| Didn't you read the article? That form is deprecated. The
| recommended one is C,++,++
| PaulDavisThe1st wrote:
| You clearly didn't read it either. Going forward, it will
| be C++...
| PaulDavisThe1st wrote:
| >If the major version were to change, there wouldn't be any
| need for backward compatibility with the existing code,
|
| I have no idea where you get this idea from. I expect gcc v28
| to be able to compile C++ from 2008, and I'm not alone in that.
| recursivecaveat wrote:
| I mean this is extremely minor, but the more incompatibility
| you create the slower the uptake will be. In the extreme you
| could create a Python 2->3 situation over old syntax.
| HackerThemAll wrote:
| Yes, but no. I learned C++ in '90s when it was C with classes and
| some other noise added by Stroustrup. During the some 25 years
| that followed it had became a mess that's insanely hard to work
| with. I'm not going back to this language. I prefer plain C or
| Rust, leaning towards Rust when I fully comprehend the lifetime
| and borrow checker. Or when I have the luxury of having a GCed
| runtime, then the .NET with its easiest C# language with
| wonderful abundance of great libraries is the best choice. Nobody
| was ever fired for using .NET (for right purposes).
| PaulDavisThe1st wrote:
| Tiring how often this needs to be said, but if you want "C with
| classes", you can just use C++ that way.
|
| I've been using C++ for more than 30 years (I added
| thread_local to Cfront back in the early 90s), and while the
| language has grown dramatically in that time, there is
| fundamentally nothing that would prevent me from writing "C
| with classes" using the modern version.
|
| I don't do that because I also like RAII, and polymorphism, and
| operator overloading and ...
|
| I've never used .NET and could not imagine any scenario under
| which I would. The libraries that matter to me are mostly
| written in C or C++ and there are more of them than I'd ever
| need, mostly.
| QuadmasterXLII wrote:
| Languages are both read and written, restrictions like OP is
| pining for are fundamentally for reading. As such, it is not
| terribly helpful that they can opt in to restrictions when
| writing.
| zabzonk wrote:
| > nothing that would prevent me from writing "C with classes"
| using the modern version.
|
| Or indeed "C without classes", just with some extra type-
| checking.
|
| And of course K&R used Stroustrup's C++ compiler to build and
| test the code for TCPL 2nd Ed.
| blueaquilae wrote:
| I'm far from C++ but reading this article confused be, from the
| form to the impact to the dead link https://www.open-
| std.org/jtc1/sc22/wg21/docs/papers/2021/p12...
|
| I guess that's a preview how C++ require a lifelong commitment.
| tialaramex wrote:
| That should probably link https://www.open-
| std.org/jtc1/sc22/wg21/docs/papers/2019/p12...
|
| The difference being that P1219R2 was actually a revised
| proposal from 2019 not 2021.
| rusakov-field wrote:
| Clarity and Elegance of Syntax > Backwards compatibility.
|
| In my opinion anyway. C++ feels so bloated these days.
___________________________________________________________________
(page generated 2026-03-15 23:00 UTC)