Live data from Hacker News

Three new utility functions in C++23

mariusbancila.ro

141–150 of 196 posts

Re: Three new utility functions in C++23

#141

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…

There are also conditional expressions to consider. With the function approach, you can effectively mark any subexpression as unreachable, so e.g. this is possible:

   auto x = (y == 1) ? foo :
            (y == 2) ? bar :
            ...
            std::unreadchable();

Re: Three new utility functions in C++23

#142
post #130
post #10

Earlier quoted context omitted.

How is that "better advice"? Big endian architectures are pretty much dead (x86, ARM and RiscV are all little endian; some ARM chips are bi-endian, but not Apple's) and there's no discernible compelling advantage that would allow a comeback. You absolutely want to specify the byte order in new protocols as little endian.

There are still big-endian-only ARM chips out there, and some of them are basically the only processors in their class (TMS570 in particular); while I wish they were bi-endian, big endian platforms are still alive and well.

There's still way, way more little-endian platforms, and it's not likely to change in the future. So it makes sense to use the representation that's most efficient for them when designing protocols.

Re: Three new utility functions in C++23

#143

Earlier quoted context omitted.

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…

There are also conditional expressions to consider. With the function approach, you can effectively mark any subexpression as unreachable, so e.g. this is possible: auto x = (y == 1) ? foo : (y == 2) ? bar : ... std::unreadchable();

[deleted]

Re: Three new utility functions in C++23

#144

Earlier quoted context omitted.

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(i…

Technically these would still produce different results if y started two bytes after x -- I can't remember if that is itself legal however!

Re: Three new utility functions in C++23

#145
post #130

Earlier quoted context omitted.

There are still big-endian-only ARM chips out there, and some of them are basically the only processors in their class (TMS570 in particular); while I wish they were bi-endian, big endian platforms are still alive and well.

There's still way, way more little-endian platforms, and it's not likely to change in the future. So it makes sense to use the representation that's most efficient for them when designing protocols.

The efficiency difference is negligible; the cost of an in-register byte swap is basically zero compared to the cost of getting the word from memory into the register to begin with. The bigger deal is making sure that people remember that we /are/ still in a bi-endian world, and writing protocols and code with that in mind.

Re: Three new utility functions in C++23

#146
post #121

Earlier quoted context omitted.

std::unreachable() feels like it's what std::assert(false) should be, except that std::assert(false) is bizarrely defined (as a no-op) when NDEBUG is defined. This is one of those strange cases where the spec defines behavior that I'd strongly expect to be undefined.

What's bizarre about asserts being disabled if you explicitly ask for it?

I'm not asking for the assert to be disabled. I'm asking for debugging features to be disabled. (NDEBUG == "no debug.") The debugging feature of an assert statement is that it performs work to check if the assertion is true and provides diagnostics if not. Disabling the debugging feature of an assert would, in my mind, make it purely an assertion -- an assumption that the compiler can count on (since this is true by design and demonstrated during debugging). Which is to say, it becomes undefined (contrary to compiler assumptions) if the condition is false.

Another way of thinking of this: With NDEBUG undefined, the sequence `assert(condition); if(!condition) action();` is perfectly reasonable and equivalent to the naked assert. But, because assert(false) is defined, defining NDEBUG changes the semantics of the code, with the two examples having identical behavior when NDEBUG is unset, and different behavior when NDEBUG is set. This is contrary to my understanding of the intent of NDEBUG, to suppress debugging information without changing semantics.

A third view: With NDEBUG undefined (which is normal for test and development), /I have no way of testing what happens past an assert(false)/. If I then define NDEBUG for a release build, I'm by definition exposing my user to untested code. The compiler might (with a defined assert(false)) define the behavior of this new code, /but I cannot, since I can't test it./ It just makes more sense to acknowledge that anything past an event horizon is undefinable, and call it undefined.

Re: Three new utility functions in C++23

#147
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…

> Technically, this isn't the case in C either: the type defaults to `int`, but the compiler will pick a larger type if necessary, e.g. `enum Z { a = ((long long)INT_MAX) + 1 };`

if you read this and alarm bells didn't ring in your head I really invite you to immediately go check any enum you may have defined in your code because this is absolutely false with MSVC in C++ (https://gcc.godbolt.org/z/6bqW9rE81) (and C is often compiled as C++ on windows)

Re: Three new utility functions in C++23

#148

Earlier quoted context omitted.

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…

There are also conditional expressions to consider. With the function approach, you can effectively mark any subexpression as unreachable, so e.g. this is possible: auto x = (y == 1) ? foo : (y == 2) ? bar : ... std::unreadchable();

You could can 'inject' it via writing a function never_fails, that tests the condition, and branches to unreachable if it fails, then returns the same condition. That should let the compiler understand that the condition is always true.

Re: Three new utility functions in C++23

#149
post #114

Earlier quoted context omitted.

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.

That’s a pretty surprising opinion. Variadic templates are extremely widely used and there’s no simple replacement (e.g. how would you implement something like emplace_back without them?) Span is trivial to replace with a third party library.

Re: Three new utility functions in C++23

#150

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…

Herb Sutter’s Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14
Post reply on HN