Live data from Hacker News

Three new utility functions in C++23

mariusbancila.ro

101–110 of 196 posts

Re: Three new utility functions in C++23

#101
post #53

Earlier quoted context omitted.

Directives are attached to functions, like abort() has the [[noreturn]] attribute, so compilers don't have to emit any code that would run after it returns, or save anything on the stack. std::unreachable() goes a step further, and tells the compiler that it doesn't even have to emit the call instructions or any instructions leading up to it.

Yeah obviously it's a compiler intrinsic. That's not what I or the person I was replying to was saying, and wasn't the relevant point. We were saying how else could you give the compiler an intrinsic, without a call of some kind? Like what other syntactic mechanism is there you can treat as an intrinsic in the compiler.

Sorry, I misread it as wanting a different mechanism. Which I don't think is needed. Some compilers used #pragma for it, but that was ugly and ill-specified, and made it hard to work around missing features by defining your own version.

Re: Three new utility functions in C++23

#102

My first impression is that all three of these are clutter to an already very cluttered language ... 1.) Coming from embedded programming, I can see the utility of `std::unreachable`. But shouldn't this be a compiler directive? Or a standardized #pragma? Can someone more knowledgeable in C++ say whether using functions as markers is a common mechanism in std:: ? 2.)Maybe the example is bad here, as it doesn't even sa…

Is there syntax available in C++ to write some kind of instruction to the compiler which is not some kind of call? Even __builtin_trap is a call isn't it? What else could you attach a directive to?

c++11 style attribute. There are already similar attributes [[unlikely]] and [[likely]] which can be attached to any statement. Having [[unreachable]] wouldn't be that surprising. C++23 also introduced [[assume(expr)]] which is basically conditional unreachable. I don't see a reason why standard committee couldn't have defined that [[assume(false)]] can be used for that purpose instead of new builtin. Either of the two would have been more consistent in my opinion, only reason I see for choosing a builtin function is because GCC and Clang already had __builtin_unreachable() builtin functions, so making it a function might in theory reduce the work for them.

Re: Three new utility functions in C++23

#103

Earlier quoted context omitted.

Is there syntax available in C++ to write some kind of instruction to the compiler which is not some kind of call? Even __builtin_trap is a call isn't it? What else could you attach a directive to?

c++11 style attribute. There are already similar attributes [[unlikely]] and [[likely]] which can be attached to any statement. Having [[unreachable]] wouldn't be that surprising. C++23 also introduced [[assume(expr)]] which is basically conditional unreachable. I don't see a reason why standard committee couldn't have defined that [[assume(false)]] can be used for that purpose instead of new builtin. Either of the t…

Apparently you can add attributes to case labels, so yeah that does work.

Re: Three new utility functions in C++23

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

Re: Three new utility functions in C++23

#105
post #47

My first impression is that all three of these are clutter to an already very cluttered language ... 1.) Coming from embedded programming, I can see the utility of `std::unreachable`. But shouldn't this be a compiler directive? Or a standardized #pragma? Can someone more knowledgeable in C++ say whether using functions as markers is a common mechanism in std:: ? 2.)Maybe the example is bad here, as it doesn't even sa…

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…

> Plus, if a new compiler shows up (besides MSVC/GCC/LLVM)

They are still far from being the only game in town.

Re: Three new utility functions in C++23

#106
post #47

My first impression is that all three of these are clutter to an already very cluttered language ... 1.) Coming from embedded programming, I can see the utility of `std::unreachable`. But shouldn't this be a compiler directive? Or a standardized #pragma? Can someone more knowledgeable in C++ say whether using functions as markers is a common mechanism in std:: ? 2.)Maybe the example is bad here, as it doesn't even sa…

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 specific, but handling compiler specific behavior is one of the main purpose of pragmas.

Re: Three new utility functions in C++23

#107
post #105
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…

> Plus, if a new compiler shows up (besides MSVC/GCC/LLVM) They are still far from being the only game in town.

That was unclear on my part, but I meant a new compiler in terms of "new to the project", not "new to the C++ community". The linked SO answer only covers those three compilers, which illustrates the issue I was talking about (you need to add a new `#elif` branch)

Re: Three new utility functions in C++23

#108

Earlier quoted context omitted.

One thing people are missing is that you may need to use this to satisfy conditions that the compiler might encounter to emit a warning (or error if equivalent of -Werror is enabled). If you have strict warnings on, but no way to tell the compiler that a location should not be reachable, you wind up in situations where you are doing something like `assert(!"not reached!")` and it won't be enabled in all build types.…

For that abort() is just fine. Being UB, unreachable is more about optimizations .

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();
    }

Re: Three new utility functions in C++23

#109

I understand why it's there, but I do find it fun that when many people are trying to reduce undefined behaviour in their code, std::unreachable is literally defined as "this is undefined behaviour, use that to optimise". I suspect 99.9% of uses of std::unreachable would be better replaced by abort. (There will be those times when the code is correct and the optimisation gains are worth it -- but they will be rare).

https://gcc.gnu.org/onlinedocs/gcc/extensions-to-the-c-langu...

The rational is better explained there :)

Most programmers will write an error message and halt execution flow (return EXIT_FAILURE, abort(), exit() or even an exception). The hint about assembler give cares about special (maybe optimized or machine specific) code or embedded stuff. And the second example refers explicitly to functions which do exit() and never return actually. The committee tidies up stuff. Something which compilers provide individually is becoming standard.

Re: Three new utility functions in C++23

#110

Earlier quoted context omitted.

For that abort() is just fine. Being UB, unreachable is more about optimizations .

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.
Post reply on HN