Live data from Hacker News

Three new utility functions in C++23

mariusbancila.ro

111–120 of 196 posts

Re: Three new utility functions in C++23

#111
post #47

Earlier quoted context omitted.

1. It is a compiler defined function (`__builtin_unreachable()`), but the issue is that MSVC doesn't have it, so you need a different implementation per compiler [0]. Plus, if a new compiler shows up (besides MSVC/GCC/LLVM), you'd need to investigate what the correct way to express `__builtin_unreachable` is. From a compiler perspective, using a function makes the most sense, since that fits into the existing control…

>Pragmas are processed by the pre-processor This is wrong a lot of pragmas, I would even say most pragmas are not handled by preprocessor. Some examples: pragma pack, warning control, pragma GCC unroll, per function optimization setting changes, all the pragmas which 1:1 map to c++11 style attributes. None of that is handled by preprocessor, pragma once seems like rare one which is. Yes all of them are compiler speci…

I meant that they are processed before any syntactical analysis, so they're not particularly useful for this kind of thing. For example, these are all wrong usages of our hypothetical `#pragma unreachable`:

    void foo();
    #pragma unreachable
    class bar
    {
    #pragma unreachable
    };
    namespace foobar {
    #pragma unreachable
    }
But pragmas can generally be used anywhere, barring tokenization issues. The end result is that `pragma unreachable` would likely end up turning into a magic function call inside the compiler, since it really only makes sense in a spot where you can invoke a function.

Also, I think you are conflating pragmas with `__attribute__`, which is how you set per function optimization settings. If you do that with pragmas, then it isn't limited to a single function.

Re: Three new utility functions in C++23

#112

I think -- I hope? -- we're seeing the death spiral of this language. C++'s Biggest Problem: unbelievable, extraordinary, just mind-blowing levels of complexity. Solution: add more stuff!

I don’t necessarily disagree with the underlying point, but this it’s a weird change to comment on.

The complexity explosion in C++ is due to extra language features etc. not 3 extra, probably well documented, quality of life functions in the standard library.

std::unreachable is the most atypical “function” in this post, but from a code readability perspective, it is pretty clear what it does and it doesn’t really add any new concepts to the language (UB has always been a footgun).

Also, if you want to preserve backward compatibility, all you CAN do is add more abstractions and hope they are simpler to understand and cover the majority of the use cases that the old ones did.

Re: Three new utility functions in C++23

#113
Kind of off topic, but is there a good "catch up" guide for people who stopped paying attention after C++11? Like a quick summary of just the useful, practical things you'd actually want to use in production, rather than the parts that are only interesting to computer science academics? Most of the "what's new in C++X" guides seem to just dump everything on you at once. I feel like I should get back into C++ but I don't think I really need to care about folding expressions or std::bit_cast.

Re: Three new utility functions in C++23

#114
post #41

Why on earth are these in C++23 and not C++11? There are a ton of things that should’ve been standardized over a decade ago but only show up in C++20 or later. `std::span ` is a huge one. The mind boggles.

To get something into C++ someone has to actually write a paper and propose it to the standards committee who has to vote and agree on it. You can't just have some dude write a span.hpp and go "yep, that's going into my compiler v2" - not how standards work.

I would’ve much rather have gotten span into C++11 than variadic templates, for instance. Definitely seems to me like a paper about span would’ve been a lot shorter and easier to write than one about variadic templates.

Re: Three new utility functions in C++23

#115

Earlier quoted context omitted.

If a code path that's supposed to be unreachable is reached then the program is already broken. Unless it has a bug, a compiler will not make a program more broken. At worst (or best, depending on how you look at it) it will only make any bugs it already has more obvious.

It's undefined behavior. The compiler is free to do whatever, including making your program more broken.

I find it unhelpful to frame undefined behavior as an “escape hatch” that lets the compiler do anything it wants. Compiler writers aren’t gleefully hunting for issues and using its presence as an excuse to make your life miserable. Instead, the weirdness arises because the compiler makes certain assumptions and transforms the code in ways that depend on them. For example:

1. Null pointers are never dereferenced.

2. Ptr *p is dereferenced.

3. p therefore cannot be null.

4. Ergo, we can omit checking whether p is null.

If the initial premise isn’t actually true (i.e., you slip up and dereference a null pointer), the chain of logic breaks down and boom! Applying many such rules can certainly lead to weird emergent behavior—and maybe you should act as if anything can happen—but it’s not a total free-for-all.

Re: Three new utility functions in C++23

#116

Kind of off topic, but is there a good "catch up" guide for people who stopped paying attention after C++11? Like a quick summary of just the useful, practical things you'd actually want to use in production, rather than the parts that are only interesting to computer science academics? Most of the "what's new in C++X" guides seem to just dump everything on you at once. I feel like I should get back into C++ but I do…

I found Stroustrop's book A Tour of C++ very useful for catching up with C++14/17. It's relatively short and it's easy to skim through parts you already know well.

It was just updated for C++20 (with some coverage of C++23).

There's always a bunch of CppCon talks for this too. Just pop on over to their YouTube channel.

Re: Three new utility functions in C++23

#117

Kind of off topic, but is there a good "catch up" guide for people who stopped paying attention after C++11? Like a quick summary of just the useful, practical things you'd actually want to use in production, rather than the parts that are only interesting to computer science academics? Most of the "what's new in C++X" guides seem to just dump everything on you at once. I feel like I should get back into C++ but I do…

[deleted]

Re: Three new utility functions in C++23

#119
post #111

Earlier quoted context omitted.

>Pragmas are processed by the pre-processor This is wrong a lot of pragmas, I would even say most pragmas are not handled by preprocessor. Some examples: pragma pack, warning control, pragma GCC unroll, per function optimization setting changes, all the pragmas which 1:1 map to c++11 style attributes. None of that is handled by preprocessor, pragma once seems like rare one which is. Yes all of them are compiler speci…

I meant that they are processed before any syntactical analysis, so they're not particularly useful for this kind of thing. For example, these are all wrong usages of our hypothetical `#pragma unreachable`: void foo(); #pragma unreachable class bar { #pragma unreachable }; namespace foobar { #pragma unreachable } But pragmas can generally be used anywhere, barring tokenization issues. The end result is that `pragma u…

This is the intent and purpose of _Pragma; it provides a way to use existing #pragmas that are tokenized and handled a bit later, so they can e.g. be included in macro expansions.

Re: Three new utility functions in C++23

#120

Earlier quoted context omitted.

The literal example in the Clang documentation is not about optimization: > For example, without the __builtin_unreachable in the example below, the compiler assumes that the inline asm can fall through and prints a “function declared ‘noreturn’ should not return” warning. void myabort(void) __attribute__((noreturn)); void myabort(void) { asm("int3"); __builtin_unreachable(); }

Right elsethread I said that it is both about optimizations and static analysis. That's a static analysis case.

It seems like optimization cases where this makes sense are generally of the sort where `noreturn` can't be used because it is conditional. That makes sense to me (although, could this have covered most use cases by making `noreturn` support being passed the name of a function argument?).

One example was interesting, though. I could see someone believing these might produce the same optimized assembly (-O2):

  void a(int& x, int& y) {
    if (&x == &y) __builtin_unreachable();
    x ^= y; y ^= x; x ^= y;
  }
  
  void b(int& __restrict x, int& __restrict y) {
    x ^= y; y ^= x; x ^= y;
  }
However, it produces:

  a(int&, int&):                               # @a(int&, int&)
        mov     eax, dword ptr [rdi]
        xor     eax, dword ptr [rsi]
        mov     dword ptr [rdi], eax
        xor     eax, dword ptr [rsi]
        mov     dword ptr [rsi], eax
        xor     dword ptr [rdi], eax
        ret
  b(int&, int&):                               # @b(int&, int&)
        mov     eax, dword ptr [rsi]
        mov     ecx, dword ptr [rdi]
        mov     dword ptr [rsi], ecx
        mov     dword ptr [rdi], eax
        ret
Is this something compiler contributors would optimize once they know about it? Similar question probably exists with using `__builtin_unreachable` if values aren't aligned versus `__builtin_assume_aligned`.

I'd love to see these things illustrated with more real-world examples.

Post reply on HN