[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)