[HN Gopher] C++26: Pack Indexing
       ___________________________________________________________________
        
       C++26: Pack Indexing
        
       Author : HeliumHydride
       Score  : 49 points
       Date   : 2025-01-24 19:27 UTC (3 hours ago)
        
 (HTM) web link (www.sandordargo.com)
 (TXT) w3m dump (www.sandordargo.com)
        
       | foota wrote:
       | This is nice, but I'm still waiting for a constexpr for loop to
       | use it with.
        
         | mystified5016 wrote:
         | Can we have constexpr math functions like sqrt already?
        
           | Maxatar wrote:
           | My understanding is that all of the functions found in the C
           | compatibility headers that the C++ standard defines can not
           | be made constexpr. sqrt is among them, as are a lot of the
           | math functions.
        
             | agosz wrote:
             | The compatibility can be solved with macros to toggle it on
             | or off depending on how you're building. C++26 has
             | constexpr sqrt.
        
               | pjmlp wrote:
               | There is a paper suggesting to replace all macro based
               | code, due to way modules work.
               | 
               | https://www.open-
               | std.org/jtc1/sc22/wg21/docs/papers/2025/p26...
        
           | stefanos82 wrote:
           | Seems like since C++26, it does use constexpr
           | https://en.cppreference.com/w/cpp/numeric/math/sqrt
        
         | logicchains wrote:
         | If you want to iterate over the whole thing you can just use a
         | fold expression, which arguably look cleaner than the non-
         | compiletime ways to map over a collection like std::transform.
        
           | a_t48 wrote:
           | Even with fold expressions, sometimes you need the actual
           | index. See here https://github.com/basis-
           | robotics/basis/blob/ca70aee6daca37c... - I did use a fold
           | expression, but I needed the actual index in the fold
           | expression to both do array access and to pass down into a
           | template parameter.
        
           | foota wrote:
           | Arguably is doing a lot of work here, peoples eyes tend to
           | start glazing over when I tell them it's a parameter pack
           | fold :) I'd much rather have a loop that doesn't confuse
           | people not familiar with the syntax.
        
         | a_t48 wrote:
         | Pretty please.                   [&]<std::size_t...
         | I>(std::index_sequence<I...>) {
         | (SetupInput<I>(options, transport_manager,
         | subscriber_queues[I], thread_pool,
         | templated_topic_to_runtime_topic),            ...);
         | }(std::make_index_sequence<INPUT_COUNT>());
         | 
         | would be a lot more readible as                   for
         | constexpr( size_t I = 0; I < INPUT_COUNT; I++ )
         | SetupInput<I>(options, transport_manager, subscriber_queues[I],
         | thread_pool, templated_topic_to_runtime_topic);         }
         | 
         | Yes, there's some syntax snags around it (right now I looks
         | mutable, something like `for (constexpr size_t I :
         | INPUT_COUNT)` might be better), but there has to be some sane
         | middleground.
        
           | moonshadow565 wrote:
           | P1061 is in C++26 so you can instead do:
           | const auto [...I] = std::make_index_sequence<INPUT_COUNT>{};
           | ((SetupInput<I>(options, transport_manager,
           | subscriber_queues[I], thread_pool,
           | templated_topic_to_runtime_topic)),...);
           | 
           | yay!
        
             | foota wrote:
             | Oh, that is nice!
        
           | spacechild1 wrote:
           | > right now I looks mutable, something like `for (constexpr
           | size_t I : INPUT_COUNT)` might be better
           | 
           | I thought the same, but then you lose the ability to control
           | the increment step. For example, one might want to iterate
           | pairwise.
           | 
           | Regarding syntax, you could mandate that the loop variable
           | has to be declared `constexpr` as well, which makes it clear
           | that it can't be modified in the loop body.
        
         | pragma_x wrote:
         | It's been ages since I've done metaprogramming with C++. I had
         | to look this up, since my first reaction was: just use
         | recursion! Yeah, I can see why a for-loop is the preferred way
         | to go here.
         | 
         | Turns out that const-call depth is limited to 512, but by
         | implementation, not by the standard (which is undefined).
         | 
         | https://stackoverflow.com/a/9320911/713831
        
           | foota wrote:
           | There's a way to "iterate" over parameter packs called fold
           | expressions, but they're painful and look very weird.
        
             | plorkyeran wrote:
             | I don't find them painful, but they're definitely extremely
             | weird looking. The fact that they're "fold expressions" but
             | are normally used with operator comma to sequence together
             | things that want to be statements is a pretty strong sign
             | that something went wrong in the design process.
        
         | beached_whale wrote:
         | template for is proposed for 26 as part of the reflection
         | papers.
        
       | edflsafoiewq wrote:
       | C++ continues its long journey to making its template system an
       | actual usable programming language.
        
         | kubb wrote:
         | It's unfortunate that it had to happen by accident, and now new
         | features are reluctantly being pushed through piecemeal.
         | 
         | Imagine what it could have been if it was designed for
         | programmability from the start.
        
           | klipt wrote:
           | > Imagine what it could have been if it was designed for
           | programmability from the start.
           | 
           | Circle C++ compiler was designed for that:
           | https://www.circle-lang.org/quickref.html
        
           | nxobject wrote:
           | I do think as well that some deeper scrutiny of semantics
           | with the tools of PL research might have helped ahead of time
           | - some of the most glaring warts like the perfect forwarding
           | problem, or the need for reference collapsing, would have
           | been avoided if the standards committee had taken a more
           | rigorous approach to understanding semantics and their
           | implications. I hope Zig's comptime will get that level of
           | scrutiny.
        
           | kazinator wrote:
           | It would have been a huge, sudden increment in complexity
           | from absolute zero, causing it to be forever written off and
           | ignored as an incomprehensible curiosity looking for a
           | practical application.
           | 
           | You have to suck people in with, "hey, you can write these
           | two similar C-like functions under one definition, the
           | correct one of which is automatically deduced and used".
        
         | papichulo2023 wrote:
         | I like to code in cpp as a hobby (computer vision stuff) but
         | avoid template programing like the plague. The part of std is
         | already scary stuff with 50 lines of errors for single typo.
        
           | edflsafoiewq wrote:
           | It's actually becoming easier as they make it a real
           | programming language.
           | 
           | The infamous template error messages are generally a result
           | of two things: first, too many candidate functions because
           | logic is cobbled together out of a nest of SFINAE overloads,
           | which is ameliorated by moving the logic into normal code
           | with if constexpr, etc; and second, type errors occurring
           | deep in the call/expansion stack because unchecked values
           | keep getting passed on just like in a dynamically typed
           | language (which TMP basically is), which is ameliorated by
           | moving the type checks higher up in the stack with concepts
           | or static_assert.
        
           | mb7733 wrote:
           | > 50 lines of errors for single typo
           | 
           | 50? That's it!? I work in a code base where a previous
           | developer went nuts with overloads and I routinely get
           | hundreds of lines of output for a single compiler error.
        
           | npalli wrote:
           | >The part of std is already scary stuff with 50 lines of
           | errors for single typo.
           | 
           | IDE's make this less of a problem.
        
           | dkersten wrote:
           | I personally quite like templates and constexpr. I don't do
           | anything too crazy with them, but I like being able to write
           | code that will compile down to efficient code without runtime
           | checks. I tried to write equally generic code in typescript
           | recently and I had to make peace with the fact that I had to
           | pay for either an indirect call through inheritance or a
           | runtime conditional, where in C++ I could use template code
           | and a constexpr if to choose the correct code path at compile
           | time.
        
           | rerdavies wrote:
           | I code cpp professionally. But I still dread template
           | programming. Pretty much a guarantee that I'm going to end up
           | spending an afternoon wading through horrifyingly inscrutable
           | error messages.
        
           | pjmlp wrote:
           | After C++17, template programming has become relatively easy.
           | 
           | You can use enable_if and static_assert, alongside type
           | traits to check the types, and give useful error messages.
           | 
           | With C++20 you get concepts lite, which while not being as
           | good as C++0x concepts, still simplify the code a lot,
           | improve error messages, and remove the need for the classical
           | tricks, when used alongside constexpr.
           | 
           | No need to go crazy with them.
        
           | paulddraper wrote:
           | Save often, compile often
        
           | dgfitz wrote:
           | I also refuse to touch templates. Never needed them, never
           | liked them. When I work on code that utilizes templates in
           | c++, it reaffirms this feeling.
        
           | mianos wrote:
           | 50 lines? For std io I get 100s of lines of candidate
           | suggestions. It's so dumb. I usually turn off the suggestions
           | error. Only about 35 years as a C++ developer so maybe I will
           | become less grumpy about template errors as I age.
        
         | pjmlp wrote:
         | Which I actually find more approachable than how Rust deals
         | with two macros systems, each with its own mini language.
         | 
         | At least, as convuluted as C++ may be, template and compile
         | time programming still rely on C++.
        
           | necubi wrote:
           | I'm not necessarily going to defend proc macros, which have a
           | lot of problems but are also better than the alternative in
           | many languages (like Go's over-reliance on codegen). Macros-
           | by-example are pretty nice though, even with the special
           | syntax.
           | 
           | But in Rust, you don't need to delve into any kind of macro
           | for polymorphism like you do in C++, since Rust has a real
           | generics system. There is vastly more C++ code that
           | instantiates templates than Rust code that uses macros.
        
             | pjmlp wrote:
             | There are enough ways to do polymorphism in C++ without
             | touching macros.
             | 
             | Given that Rust IO and many crate attributes are macro
             | based, not sure who wins out.
        
               | necubi wrote:
               | I was a bit unclear there--I was referring to templates,
               | not C++ macros. I believe that concepts in C++20 have
               | improved the situation (although I haven't personally
               | worked with a C++20 codebase and don't know how widely
               | adopted it is in the ecosystem).
        
             | cherryteastain wrote:
             | In modern C++, you don't need macros for polymorphism at
             | all
        
               | marginalia_nu wrote:
               | Unless this is about some particular technique I've
               | missed, isn't this what virtual methods are for? Only
               | place I'm aware of where you see macros-based
               | polymorphism is in C.
        
               | cherryteastain wrote:
               | Virtual methods are runtime polymporphism. Templates are
               | compile time polymorphism, and therefore typically are
               | faster (more inlining + avoiding virtual function call).
        
         | jovial_cavalier wrote:
         | Am I crazy for thinking this is (mostly) useless?
         | 
         | It feels like programming in the last five years has turned
         | into a competition of who can make the most abstract meta
         | programming patterns. I think if you find yourself making use
         | of this feature, you're probably in a deep hole of your own
         | making.
         | 
         | What is an example of a useful function that takes an arbitrary
         | number of arguments each of which has an arbitrary type that
         | isn't as trivial as the examples given in the article? For
         | super trivial stuff this is useful, and if std used this under
         | the hood to provide std::first_arg or something, that would
         | make sense. But the absence of this language feature doesn't
         | really seem like it's holding back 99.9% of users.
        
           | foota wrote:
           | People writing generic libraries need this. As an example,
           | I've seen it used a lot in anything related to logging and
           | monitoring, since these generally need the ability to take
           | arbitrary data types and work with them in different ways.
           | The same is true for database APIs, etc.,.
        
           | HeliumHydride wrote:
           | std::print is one. You need variadic generics to make it
           | work.
        
       | suby wrote:
       | I don't have a source, but I have read that the reason this
       | wasn't originally introduced into C++ was because they couldn't
       | agree on what the syntax would be. So much pain because the
       | committee is dysfunctional, it took a decade plus to introduce
       | something that everyone from the start wanted and understood
       | would improve things. Par for the course with C++.
        
         | rerdavies wrote:
         | At least it's progress over the first decade of C++'s life
         | where NOTHING happened.
        
         | spacechild1 wrote:
         | > I don't have a source, but I have read that the reason this
         | wasn't originally introduced into C++ was because they couldn't
         | agree on what the syntax would be
         | 
         | I can totally imagine that. That's double ironic because the
         | syntax is pretty obvious (which I find pretty surprising for a
         | new C++ feature :)
         | 
         | But yeah, it's amazing that we only get this 15 years(!) after
         | the introduction of variadic templates. I can totally see why
         | some languages would decide against ISO standardization.
        
         | mkoubaa wrote:
         | Suppose c++ is around for 100 more years (i'll take the over).
         | 
         | Sacrificing a couple decades in order to get the syntax just
         | right is worth it. Just look at... Javascript.
        
           | int_19h wrote:
           | Yeah, but then look at C++ - does the syntax really look like
           | it's "just right" to you? Modern JS features actually tend to
           | have cleaner syntax, generally speaking.
        
       | a_t48 wrote:
       | I usually find myself putting parameter packs into tuples and
       | then using `std::get` on the tuple to index. It's not perfect
       | (will end up making copies), but has the side benefit of being
       | able to additionally store the parameter pack for later.
        
       | int_19h wrote:
       | Zig's approach to generics and metaprogramming - treating
       | functions and types as first-class compile-time values in the
       | base language - makes more and more sense.
        
       | psyclobe wrote:
       | C++ parameter packs are really bad ass, super cool to see this
       | added
        
       ___________________________________________________________________
       (page generated 2025-01-24 23:00 UTC)