Live data from Hacker News

C++26 is done: ISO C++ standards meeting Trip Report

herbsutter.com

391–400 of 437 posts

Re: C++26 is done: ISO C++ standards meeting Trip Report

#391

Earlier quoted context omitted.

I don't agree. Null is an artefact of the type system and the type system evaporates at runtime. Even C's NULL macro just expands to zero which is defined in the type system as the null pointer. Address zero exists in the CPU, but that's not the null pointer, that's an embarrassment if you happen to need to talk about address zero in a language where that has the same spelling as a null pointer because you can't say…

Null doesn't expand to zero on some weird systems. tese days zero is special on most hardware so having zero and nullptr be the same is importnt - even though on some of them zero is also legal.

Historically C's null pointer literal, provided as the pre-processor constant NULL, is the integer literal 0 (optionally cast to a void pointer in newer standards) even though the hardware representation may not be the zero address.

It's OK that you didn't know this if you mostly write C++ and somewhat OK that you didn't know this even if you mostly write C but stick to pre-defined stuff like that NULL constant, if you write important tools in or for C this was a pretty important gap in your understanding.

In C23 the committee gave C the C++ nullptr constant, and the associated nullptr_t type, and basically rewrote history to make this entire mess, in reality the fault of C++ now "because it's for compatibility with C". This is a pretty routine outcome, you can see that WG14 members who are sick of this tend to just walk away from the committee because fighting it is largely futile and they could just retire and write in C89 or even K&R C without thinking about Bjarne at all.

Re: C++26 is done: ISO C++ standards meeting Trip Report

#392

Earlier quoted context omitted.

I don't understand this at all. There are modules. But headers are perfectly fine to deal with and have been for decades and decades! Next you'll be arguing that contents pages in all books should be removed.

What an absurd attitude. The gymnastics to avoid circular inclusions alone are something nobody should be giving a thought to in the 2000s. "But headers are perfectly fine to deal with and have been for decades and decades!" I would have thought this was a joke... but your follow-up indicates otherwise. So what are you going to float next? "So what if people broke their arms hand-cranking their cars to start them! Pe…

I honestly don't understand. Circular inclusions are something to deal with, but it's a tree.... so how can a leaf contain a branch??

I know C# does some magical things (I know not what) to avoid this since there are no headers so you can refer to something in the same assembly/namespace thingy, but it's very different to how C++ compiles and links?

I wasn't saying that progress should be stinted, but that complaining about something with the expectation that it magically be solved is a strange view of the world. Do you also just assert that poverty and war shouldn't exist?

Re: C++26 is done: ISO C++ standards meeting Trip Report

#393
post #278

Earlier quoted context omitted.

What do you mean by a destructing move? Are you trying to avoid use of a moved object after you've moved it? eg. B = std::move(A); // You are worried about touching A when it's in this indeterminate state?

destructive moves are required to make moves zero cost. Currently move semantics in C++ requires that A is left in a 'moved from, but valid state' which means that: 1. The compiler must still generate code that calls the destructor. 2. Every destructor need have to have some flag and a test in it like: if(moved_from) // do nothing else { free_resources(); } (Granted, for some simple types the compiler might inline an…

So how would you ensure you can't do this?

A = 0; B = 0; A = move(B); ++B; ++A;

What should happen at ++B, and what should A be at the end? How would the compiler enforce this? I can see this being complicated.

The compiler can forget about it, but the code doesn't, so you mismatch between what is on screen and what the compiler does, which seems even more confusing.

Re: C++26 is done: ISO C++ standards meeting Trip Report

#394
post #278

Earlier quoted context omitted.

destructive moves are required to make moves zero cost. Currently move semantics in C++ requires that A is left in a 'moved from, but valid state' which means that: 1. The compiler must still generate code that calls the destructor. 2. Every destructor need have to have some flag and a test in it like: if(moved_from) // do nothing else { free_resources(); } (Granted, for some simple types the compiler might inline an…

So how would you ensure you can't do this? A = 0; B = 0; A = move(B); ++B; ++A; What should happen at ++B, and what should A be at the end? How would the compiler enforce this? I can see this being complicated. The compiler can forget about it, but the code doesn't, so you mismatch between what is on screen and what the compiler does, which seems even more confusing.

You pretty much need lifetime tracking to make it foolproof.

A quick dirty hack would be to have a static analyzer drop B from the symbol table after it sees std::move and give a warning, but that obviously wont catch other references to it, but maybe it will catch the low hanging fruit.

Re: C++26 is done: ISO C++ standards meeting Trip Report

#395

Earlier quoted context omitted.

> powerful compile-time and metaprogramming capabilities While I agree that, generally, compile time metaprogramming is a tremendously powerful tool, the C++ template metaprogramming implementation is hilariously bad. Why, for example, is printing the source-code text of an enum value so goddamn hard? Why can I not just loop over the members of a class? How would I generate debug vis or serialization code with a norm…

> Why, for example, is printing the source-code text of an enum value so goddamn hard? Aside from this being trivial in C++26, imo it isn't actually that tricky. Here's a very quick implementation I made awhile ago: https://github.com/Cons-Cat/libCat/blob/3f54e47f0ed182771fce...

> Aside from this being trivial in C++26

Great, it took them 51 years to make a trivial operation trivial. Call me next millennium when they start to figure out the nontrivial stuff, I guess.

Re: C++26 is done: ISO C++ standards meeting Trip Report

#396

Earlier quoted context omitted.

> powerful compile-time and metaprogramming capabilities While I agree that, generally, compile time metaprogramming is a tremendously powerful tool, the C++ template metaprogramming implementation is hilariously bad. Why, for example, is printing the source-code text of an enum value so goddamn hard? Why can I not just loop over the members of a class? How would I generate debug vis or serialization code with a norm…

Did you read the article? This is called reflection, and is exactly what C++26 introduces.

Yeah, like 50 years too late.

Re: C++26 is done: ISO C++ standards meeting Trip Report

#397
post #145
post #106

Earlier quoted context omitted.

> The fact that it knows to look for lib.rs or main.rs in src and then recursively find all my other modules without me needing to specify targets or anything like that is a killer feature on its own IMO. In the interest of pedantry, locating source files relative to the crate root is a language-level Rust feature, not something specific to Cargo. You can pass any single Rust source file directly to rustc (bypassing…

Interesting, I didn't realize this! I know that a "crate" is specifically the unit of compilation for rustc, but I assumed there was some magic in cargo that glued the modules together into a single AST rather than it being in rustc itself. That being said, I'd argue that the fact that this happens so transparently that people don't really need to know this to use Cargo correctly is somewhat the point I was making. C…

The module system in Rust is incredibly confusing for a beginner.

The standard module in Rust is basically a Rust source file (.rs) with the name of the module or a directory with a mod.rs file inside (/mod.rs). However, that alone doesn't make it a module. The root source file (lib.rs or main.rs) must declare that .rs is actually a module in the preamble via mod ;

Thus it works "backwards" in comparison to C style #include. mod doesn't include a module into the current file/module, it includes the module into the current project directory tree, which means you will never need a second mod .rs declaration again.

Re: C++26 is done: ISO C++ standards meeting Trip Report

#398

Earlier quoted context omitted.

> Nobody wanted it. The fact that the C++ standard community has been working on Contracts for nearly a decade is something that by itself automatically refutes your claim. I understand you want to self-promote, but there is no need to do it at the expense of others. I mean, might it be that your implementation sucked?

35 years is a lot longer than a decade. C++ should have copied the '= void;' syntax, too!

It should copy Zig's '= undefined;' instead of D's '= void;' The latter is very confusing: why have a keyword that means nothing, but also anything? This is a pretty common flaw within D, see also: static.

Re: C++26 is done: ISO C++ standards meeting Trip Report

#399

Earlier quoted context omitted.

> since you're not dealing with the computations directly but rather expressions (nodes) through which you are deferring the computation part until the very last moment (when you have a fully built an expression of expressions, basically almost an AST). Right, I understand that. What is not exactly clear to me is how you get from the tree of deferred expressions to the "flat" optimized expression without involving th…

The example is false because that's not how you would write an expression template for given computation so the question being how is it that the optimizer is not involved is also not quite set in the correct context so I can't give you an answer for that. Of course that the optimizer is generally going to be involved, as it is for all the code and not the expression templates, but expression templates do not require…

> The example is false because that's not how you would write an expression template for given computation

OK, so how would you write an expression template for the given computation, then?

> Expression templates do not rely on O1, O2 or O3 levels being set - they work the same way in O0 too and that may be the hint you were looking for.

This claim confuses me given how expression templates seem to work in practice?

For example, consider Todd Veldhuizen's 1994 paper introducing expression templates [0]. If you take the examples linked at the top of the page and plug them into Godbolt (with slight modifications to isolate the actual work of interest) you can see that with -O0 you get calls to overloaded operators instead of the nice flattened/unrolled/optimized operations you get with -O1.

You see something similar with Eigen [2] - you get function calls to "raw" expression template internals with -O0, and you need to enable the optimizer to get unrolled/flattened/etc. operations.

Similar thing yet again with Blaze [3].

At least to me, it looks like expression templates produce quite different outputs when the optimizer is enabled vs. disabled, and the -O0 outputs very much don't resemble the manually-unrolled/flattened-like output one might expect (and arguably gets with optimizations enabled). Did all of these get expression templates wrong as well?

[0]: https://web.archive.org/web/20050210090012/http://osl.iu.edu...

[1]: https://cpp.godbolt.org/z/Pdcqdrobo

[2]: https://cpp.godbolt.org/z/3x69scorG

[3]: https://cpp.godbolt.org/z/7vh7KMsnv

Re: C++26 is done: ISO C++ standards meeting Trip Report

#400
post #11

I am somewhat dismayed that contracts were accepted. It feels like piling on ever more complexity to a language which has already surpassed its complexity budget, and given that the feature comes with its own set of footguns I'm not sure that it is justified. Here's a quote from Bjarne, > So go back about one year, and we could vote about it before it got into the standard, and some of us voted no. Now we have a much…

I implemented Contracts in the C++ language in the early 90's as an extension. Nobody wanted it. https://www.digitalmars.com/ctg/contract.html

But then why did you add your contract system to D? You implemented your contract system in the "early 90's", and D was released in 2001, so that's near a decade of "nobody wanted it". So then why add them as a core language feature of a new programming language if no one wanted it? Why is it still a core language feature? And why object to C++ finally adding contracts. I just don't get what you're even arguing here.
Post reply on HN