C++ Club - 163. FloatZone, WG21 Varna, C++26, Contracts, Pattern matching, Reflection
Episode Date: August 4, 2023With Bjarne Stroustrup, Gianluca Delfino, Frances Buontempo, VladimÃr ArnoÅ¡t and other colleagues.Notes: https://cppclub.uk/meetings/2023/163/Video: https://youtu.be/3EWHQVHU1rM...
Transcript
Discussion (0)
Welcome to C++ Club. This is meeting 163 and today is the 13th of July 2023.
There was a bit of a pause in meetings. First, you probably heard Apple had a developer conference, so
I sort of got into the rabbit hole of watching their videos. And then I accidentally, he says, installed
their beta OS on my working machine. Which is never a good idea. And turns out that it
broke everything that's related to video, including Zoom. So I decided as a completely
sensible person to wait until another beta
refresh in two weeks and that broke it even worse. So then I spent the whole weekend
restoring the previous version and I'm fine now. So I thought we'd start with a bit of warm up, a small set of smaller topics.
This is Bartomei Filipek wrote a blog post.
It's quite old actually, but still useful.
These are all major C++17 features.
For those of us who are still on C++17,
like myself at work.
And it's a very useful blog post
in the sense that it just assembles all the main features.
And what's even more useful is that
each new feature lists compiler compatibility,
compiler support for that particular feature. Admittedly, it's a bit outdated. It's, what
is it, when it was written? October last year. Okay, it's quite a bit outdated. So compiler support has much improved since then. But still,
I thought it was a useful resource if you needed a quick refresh. This is a reddit thread about it,
and the first comment is, please the same but for C++20. So hopefully Bartomei will do that soon if he hadn't already and I missed it
and hopefully for C++23 as well.
Next is a learning resource from JetBrains. The JetBrains Academy blog posted a new course, C++ for beginners. Build a 2D
arcade game from scratch. It's a guided free course for anyone who is starting with C++.
Programming games is how many people start with C++. So yeah, that's a useful starting point where you can immediately
see the results, which is nice. A new version of CLion is out. What do they use for graphics?
Oh, good question. Hang on. I don't know. I'll clarify that for the next time. It's, I'm guessing, most likely
maybe SDL or some other game-oriented graphics library. It's always the
sort of stumbling block for novices starting to learn C++. It's installing some,
choosing some system, installing it and getting the
graphical hello world to work.
Yeah, I'll see if I can try it out and see what's it about in more detail. This
is their blog about a new release of CLion 2023.1. There are debugger updates, more support for Qt modeling language,
integration with VC package manager, better terminal emulation, better C++ support,
and all kinds of other improvements. Now you can even see disassembly in your IDE,
which can be really useful
if you're hunting for a bug
or trying to optimize heavily.
It's like Godbolt in your IDE.
This is a blog post with some other links,
like Qt Creator, for example,
which is another free IDE that you can use even if you don't use Qt.
That might be the answer to my previous question.
A new feature in Visual Studio is available,
which is called Build Insights.
It's now integrated in Visual Studio 2022.
Build Insights is based on instrumentation and tooling that had been available earlier
with VCperf build profiler. Basically it uses windows profiling architecture to produce timings for your build
and point you to anything that consumes a lot of time during the build so that you can
concentrate on optimizing it to keep your build time sane. i tried using vcperf the previous incarnation at work but unfortunately it conflicts with some
what it what it tries to do when you start it is set up a new profiling session at the system level
and even if you have admin permissions which I've got just for that particular executable. It complains about some other process
currently running some sort of system trace and I suspect this is some, I don't know,
corporate thing that can't be disabled. So I'm wondering if this feature being integrated in Visual Studio
will work better in that environment. Somehow they hadn't thought of that, which is weird.
I bet Microsoft also runs some sort of corporate tracing program on apcs. But yeah, that's an issue for me.
Right, next one is... yeah that's the reddit post. Next is documentation related.
There is a tool, I think it's originally by adobe it's called hdoc it's a
source documentation tool that produces very nice documentation websites basically statically
generated documentation about your code i think it can consume the same tags as Doxygen or close to it.
It would be lost without our 90s looking documentation automatically generated from Doxygen.
Actually Doxygen has nice post-processors now. You can find tools that modify the resulting
HTML and make it very nice looking and modern. Some of those tools even include an efficient
search. But this documentation is especially nice. So that might be an option. I think you can host it yourself and they also
provide some sort of paid hosting for your documentation if you are willing to
open it to the world. Now this is interesting, this is one of the bigger topics, although not as big as the next one.
Secret. Float zone. I only read about it a couple of days ago. This is a new
iteration of a memory and address sanitizer, which is much more efficient than the existing ASAN. It's a red zone based memory sanitizer
to efficiently detect buffer overflows and use after freeze by means of floating point underflows.
It's just genius. They provide the entire paper about this, but this website is like a summary. Basically what they do is...
let me quote from the paper, I think... quote. We introduce FloatZone, a compiler-based sanitizer
to detect spatial and temporal memory errors in C slash C++. I need to have a sort of a jingle, a ping when I read this.
Let's not make it into a drinking game.
Programs using lightweight checks that leverage the floating point unit FPU. We show that the combined effect of
lookup compare and branch can be achieved with a single floating point
addition that triggers an underflow exception in in the case of a memory
violation. Our evaluation shows that float zone significantly outperforms
existing systems with just 37% runtime overhead. As far as I can
remember, ASUN is roughly twice as slow. And then they go on with explaining this.
On every load and store, ASUN looks up the corresponding metadata,
compares it to see if it is part of a red zone, like a special memory zone set aside to detect
out-of-bound writes, and branches to exit code that raises an alarm if this is the case. The
branch instruction pollutes the branch predictor and contends with the application for CPU execution
units. The key insight in this paper is that sanitizer checks never fail in a normal case and should
add little overhead except in the event of a violation of memory safety.
In an ideal world, the sanitizer should use a special, fast instruction that is branchless,
does not contend with the application for CPU execution units, and
checks the validity of memory implicitly, raising an exception upon a violation.
While modern CPUs lack such a targeted instruction, we will show that they do have instructions
that approximate exactly this behavior.
In particular, they say, we find that a floating-point addition can be made to generate an exception if it processes red zone data.
We achieve this by configuring a single floating point addition to result in an underflow exception only if one of the operands is equal to our red zone poison value.
This is just genius.
The quote continues. By instrumenting
vulnerable loads stores with the addition, we ensure that red zone accesses raise an alarm.
Moreover, the addition is fast and branchless and executes on an execution unit that is
underutilized in most programs, which is FPU. As a result, the solution ensures high instruction
level parallelism in much better performance than prior techniques. And in the paper,
they demonstrate that they found a specific value, a quote from the website, with a magic number in hexadecimal 0B 8B 8B 8A we can implement a branchless equality check
with one of the fastest operation the process can execute floating-point
addition. This number has the unique property that when added to all the
possible floating-point values it causes an exception only with two of them. And so,
if you poison your area with these values, one of them is used for the start of the area and
the rest is filled with the other one, it sort of automatically produces an underflow if that's one of the operands. There are pictures to
illustrate this and it's just mind-blowingly cool. I wonder when... Sounds a bit hacky.
Did they try many platforms to make sure this works?
Well, fair question. I think it's currently only implemented for Clang and only on Linux.
But on the other hand, currently, at least at work, I only use sanitizers on Linux and
Clang is one of them. So even if they don't do it in GCC, still it would be a good improvement.
But according to them it should work on all x86 platforms, AMD, Intel and...
Yeah, I think that's independent. Actually there is a test implementation. So this is the PDF of the paper, it's not very long, and this is an
implementation on GitHub. They implemented it in LLVM, I think, and I'm just trying to look at what
platforms they support. I think it's just a little VM right now at the moment. Because
they used it to just... it was probably easier than GCC to play around.
Most definitely.
So yeah, that's a very interesting progress and I'm going to be watching it because that's going to improve things with sanitization.
Now on to the main topic. VANA ISO C++ Committee Trip Reports. So this is the Reddit post by by Inbal Levy. She always produces very detailed reports from all the conferences and meetings.
And so we've got a lot of new C++ 26 features. And she lists all those that were voted in. So let's quickly go through them. This paper P2558. Add ampersand, dollar sign
and backtick to the basic character set. This is approved for C23 and so C++ will mirror that with these being part of the
source character set. Hashing support for std chrono value classes.
This next paper p2562 constexpr stable sorting.
It's probably always good to have more constexpr algorithms.
Function ref, a type-erased callable reference.
This is by Vittorio Romeo and others.
I seem to remember it's been long in the making and so now it's going to be in 26.
Right. This paper P2641, checking if a union alternative is active. Previously, if you
accessed an inactive alternative, that would result in undefined behavior.
But I think this provides a way to detect which one is active.
And it's evaluated as constexpr. Yeah, useful. Another one related to function pointers and wrappers. P2548.
Copyable function. I do have already, I think it's in 23 maybe, move only function. So this is a copyable one. Presumably it's going to be still more efficient
than std function. And hopefully it's going to work well with function ref.
Yeah. There's a sub-mdspan, paper p2630. mdspan has also been long in the making. luckily we do have it in 23
i think. so this is like... oh right they say sub-mdspan was removed from m MD-SPAN paper for it to be included in 23. So this is just a re-introduction
of sub-MD-SPAN. This is a curious one. P2621. UB in my Lexa? by Corentin Jabot. The abstract says, quote, the mere act of lexing C++ can result in
undefined behavior. This paper removes that undefined behavior. And that's weird, I didn't
know that. The example is, you've probably seen this one where the source code uses a continuation backslash character and then does all sorts of weird
manipulations using the backslash, splitting the statement over several lines. And basically it's
sort of an artificial thing, but still if it can produce ub. Or another example
he lists is an unterminated string. So if you write const char star foo equals
opening double quote and don't close it, it can cause undefined behavior. Unevaluated strings, D2361. I'm not sure why
some papers have P and others have D. Different kind of paper. So this is D2361, unevaluated
strings. Quote, string literals can appear in a context where they are not used to initialize a
character array,
but are used at compile time for diagnostic messages, pre-processing, and other implementation defined behaviors. This paper clarifies how compilers should handle these things.
Yeah, fair enough. Some void star casting thing. So this is paper P2738.
Constexpr cast from void star
towards constexpr type erasure.
And the abstract is,
we propose to allow a limited form of casting
from void star to support type erasure in constexpr.
Yeah, sure.
Timo Dummler has this paper p2552 on the ignorability of standard attributes.
He says there's a general notion in C++ that standard attributes should be ignorable.
However, currently there doesn't seem does not seem to be a common understanding of what ignorable means. And this paper discusses what
kind of ignorability is there. I think it could be useful if more attributes were to be introduced.
Some other papers... user-generated static assert messages.
Oh, this one's interesting.
P2169, a nice placeholder with no name.
So this was approved.
Yeah.
The underscore can now be used as a placeholder
for variable declarations and pattern matching
in a fully backward compatible manner. So this is for entities for which a name
would provide no additional information. Like in something unused or if you have structured binding one member unused with one binding unused you can use underscore. Yeah, strong Scala vibes.
And Python, you know. If you need more than one of these unnamed entities, I don't think you can
use the same underscore twice in an expression or a binding, I guess? No, they say in revision one they did make
a use of underscore ill-formed once a placeholder has been declared in the same scope.
So yeah, in the same scope they can be only one of those.
Okay, so just as usual it's a normal identifier. Thank you. Free function linear algebra interface based on
BLAS was accepted for 26. This is p1673. This paper received consensus for further work. This is p2809.
Trivial infinite loops are not undefined behavior. We discussed it
previously and this is an existing problem. So yeah, apparently the committee agreed that
it has to be dealt with in some way. But apparently not like that. So further work was encouraged.
Of contracts there were some papers p2877 contract build mode semantics and implement
implementation strategies which received consensus. This is by Joshua Byrne and Tom Honeman.
Can you remind me what was the consensus on side effects in contracts?
There shouldn't be any, I think.
Are they not allowed by the compiler somehow?
I think they're or worrying about that if there's a side
effect on your head be it there's much more worry on my side about youB in contract expression evaluations,
which they just say, well, it shouldn't happen.
But there they don't have control.
The user has no effective control of that.
Whether I do something like a contract expression,
keep account of how many times
the contract has been executed.
I don't see that as being particularly dangerous.
It's the usual discussion between sort of purity
of functions and functions that have been instrumented to give information
about their execution I tend to favor allowing that kind of stuff so that in
interfaces are stable like what in a template function what if in a template
function I put some telemetry code in there?
Do I have to change the interface to the function to allow that to be done?
I think the answer, the nice answer is no.
Thank you. so the paper about contract violation handler p2811 received consensus for
so that's i suppose a good development but another paper related to it p2853
which proposed stood contract violation was voted against. And the quote from Reddit
goes like this. As a consequence, we removed the notion of build modes from the contracts MVP.
Every contract annotation now has one of the following three semantics ignore, observe, enforce.
And it is implementation defined which one you get. Further, we now have a consensus design
for contract violation handling. So I guess that means that the problem of only having no eval and eval and abort modes is now solved and they can proceed with
other things because that was the big one. Do I understand correctly that we will not have those two modes, we will have some sort of API
to decide what is the behavior of the API is still to be defined?
I think it's implementation defined so every implementation can do something or other
and it's up to us poor users to figure out what the implementations do and how to write portable code.
I worry about this.
We could, of course, hope that all the implementers agree on doing things the same way.
But such hopes have not always come true.
Yeah, it does sound like something that, you know, instead of hope, should be standardized.
Otherwise it's truly, I mean, admitting we're not going to be able to port
very easily from GCC to GLAN to MSVC. maybe this will sort of unclog the pipes for the contract work because that was a big thing that needed to be decided uh those two modes and now because contracts are not anymore limited to
those two build modes they can proceed with implementation and other discussions
and more bike heading.
I believe that the unclogging of the pipe was the reason for this.
What I just said here, I also said in the committee, and I also warn that there are a couple of further stages of the process after the study group.
EWG, LEWG, core, library, and then plenary.
This should be considered preliminary.
Right. Yeah, that makes sense.
So, disappointments. Networking group didn't meet and redditors are saying just use ASIO.
But on the other hand, Chris Kolhoff, according to them, stopped working with the committee.
It looks like the networking rebase on senders-receivers isn't happening.
Which is a pity.
He used to follow their progress and kept rebasing networking TS on the latest developments.
But apparently that is no more.
Other disappointments were reflection.
They just reviewed use cases and it now targets 29, but optimistic target is still 26.
So a miracle can happen. And also pattern matching. There were no developments.
And again in the table it's listed as targeting C++29, optimistically 26.
Redditors are really hoping for reflection and pattern matching in 26. Now there are some indirect signs that the work is ongoing. Like
for example this placeholder proposal. Michael Park was one of the authors and in the paper somewhere, if I can remind you of a small code snippet that's related to pattern matching.
It goes like this. inspect, parentheses foo, curly braces, underscore, ghost 2 with an arrow approximation bar. So it looks like this underscore thing was also part of the work to
enable pattern matching, hopefully. Yeah, I don't know, that's just my speculation.
Daniela Engert seems to think that as well. She posted on Mastodon, quote, the later discussions regarding pattern matching can
be found in the link provided. And the documents where the papers were pattern matching in general,
do expressions, which is also related to pattern matching, and placeholders and placeholder underscore paper. And she then says, I think there's a good
chance to complete pattern matching in 26. So looks like all these placeholder paper and do
expressions could have been yak shaving for pattern matching.
To remind you, yak shaving is, quote, what you are doing when you are doing some stupid
fiddly little task that bears no obvious relationship to what you are supposed to be working on,
but yet a chain of 12 casual relations links what you are doing to the original metatask.
I do a lot of yakshaving at work, so I'm very familiar with this term.
There's a trip report from Herb Sutter, which basically says the same thing.
Starting C++ 26, core language features and yeah
he mentions all these papers
that we mentioned
we looked at
oh yeah the reddit is discussing his
post
say quote what about networking
and
Jonathan Muller
says that's essentially dead
at the moment.
Why, someone asks.
And another one replies, quote, because they dropped executors in favor of senders and receivers.
The main proponent of networking, Chris Kolhoff, has quit spending his time with the committee
and somebody else will have to reformulate the nets in terms of senders-receivers, which is unfinished
and devolving from paper to paper. I would count at least 10 years from now for it to
happen if at all."
Another trip report from Jonathan Muller, who now apparently works at think cell and yeah he also um it's an interesting article
an interesting post and quite quite a short one so not much to read and from reddit there was
someone who said while reflection wasn't talked about at this meeting, I've heard rumors that there might be some movement soon.
Another paper that I forgot to mention
that also was apparently discussed,
a control flow operator.
A new operator for C++?
This can't be.
But apparently it received some sort of encouragement, let's say that.
This paper, number P2561 by Barry Revzin,
proposes an operator that helps those codebases that do not use exceptions
and probably will not in the future.
And there is an equivalent operator in other languages, which sort of
helps unwrap things like std expected and make the code easier to look at. I don't think
in this paper...
This paper is very interesting. And there is a lot of good points that this paper makes. I'm worried though that a good
chunk of the paper is dedicated to what should be the syntax, because I can see this
being backshattered till the next decade. Yeah, and the paper isn't proposing the exact syntax, it just discusses the possible variations.
Various parts of the committee loves discussing new syntax for things.
This one, if you get it, you can write code that is almost as simple and elegant as exception
based code.
But only or most. I think there is even a small table in the paper that
summarizes all the counterpoints to every single syntax. Yes. Yeah, this one.
Question E. E being an instance of static expected. Question E. Don't like the prefix. Try E
or try question mark E. Don't like the prefix. E three question marks. That's a bit going a bit overboard. And note, triple question mark was a trigraph for question mark and looks ridiculous,
but at least doesn't conflict with other languages. Question mark, question mark.
E! or E!, viable but seems like the wrong punctuation for something that may or may not continue.
E! continue?
Viable and not completely terrible, but doesn't seem as nice as E! try?
It's just thrown up in my mind.
I think I've seen John Skeet talking about some new operators in C Sharp,
and they've introduced the bang or exclamation for some of the nullable things.
And he's resorted to calling that the damn it operator, which I quite liked.
Sounds reasonable.
And see the code that it's generating into?
It hides complexity as opposed to eliminate it.
Yeah, there's an entire table that provides
listing of the code generated from these.
Let's say that it's certainly not a zero overhead
abstraction. It is an abstraction, but
you pay out of the nose for it. Unless there's something in
the optimizer I haven't appreciated. You always have to take that into account. But there's
conditionals in there. They're hard to optimize away. We have to count on the branch predictor
here. I am surprised that they didn't suggest try! which I think is, if I'm not mistaken,
it's a combination that may be used in Rust.
He does mention Rust, obviously.
But yeah, I'm sure someone will mention it during the endless bike sharing sessions that will follow.
But yeah, it does say there was a tri-exclamation mark in Rust.
Yes, that's the one that I'm thinking about.
Yeah, there's another report from Bartomeu Filipek.
And there was a mailing list available before the Varna meeting and there were only several
papers that caught my eye.
This one p2141 aggregates unnamed tuples. Basically it argues that we should be able to use the standard functionality
for tuple with aggregates like std get, the tuple element, and std tuple-sized and so on. Which I'm guessing could probably simplify some template metaprogramming.
This paper P2654 Macros and Standard Library Modules by Alistair Meredith. He says C++23
introduces the notion of library modules that export the whole content of the C++ standard
library, except for any parts that are defined as macros. This paper reviews the library
macros that are therefore not exported and looks for ways to export that same functionality
without requiring the module's language feature to become aware of macros. So that kind of answers the previous question you had, Gianluca, about
macros and modules. No. Narrow contracts. This is related to contracts. P2831 and others, functions having a narrow contract should not be noexcept.
This is the so-called Lakers rule, which is a long-standing design principle in the C++
standard library.
It stipulates that a function having a narrow contract should not be declared noexcept,
even if it's known to not throw when called with valid input.
In this paper we demonstrate why the
Lakers rule is still useful and important today and should not be removed.
Which sort of suggests that someone wanted to remove it. Probably related to contract work.
What is a narrow contract in this context? Let me see... Oh, there you go. A function that has no preconditions on its input
values or on the state accessible from it, i.e. a function that has defined a behavior for any
combination of input values and accessible state, is said to have a wide contract.
Examples of such functions in the C++ standard library are
stdvectorAt and stdvectorSize. If such a function is required to never throw an exception,
it may be declared noexcept. By contrast, a function that has preconditions, i.e. a function
whose behavior is undefined for some combination of input values and accessible state,
which we can call invalid, is said to have a narrow contract.
Examples of such functions in the C++ standard library are std vector operator index subscript and std vector front.
Invoking the former with an out-of-bounds index or invoking either function on an empty
vector will result in undefined behavior." So they stipulate that this should not be
accepted, because there are situations where the contract for those functions doesn't work.
Makes sense. The main point is that if something has a narrow contract,
an error can happen inside it and you could write code to detect it in many cases.
And what do you do then if it's noted? Seems logical. There was a Reddit post. Status of reflection, someone asked.
And the reply was, reflection is dead in the practical sense.
No one's working on it.
Andrew Sutton's P2237 paper is three years old.
The last paper about it is P2560 and is over a year old.
The SG7 public email archive doesn't show any discussion in over
a year. The slack channel for it is on Cpp lang, hasn't had a message in almost two years.
So it's not looking good. A slightly related post on reddit. What C++ library do you wish existed but hasn't been created yet
and somehow because people can't actually read apparently most redditors in this rate assumed
it's about the standard library which it wasn't and all the comments went into the
what had to be part of the standard library instead of just libraries.
And so one of those comments was, please give us a reflection.
And this caused an interesting discussion with some interesting comment from Jonathan Miller.
Someone said to this,
the meta classes are on their way.
The C++ committee do take long to publish their final drafts.
Then finally standardization.
Even then, it might take years
for it to appear on a compiler.
Look at the modules feature.
And Jonathan replies,
I don't know what you've heard, but metaclasses absolutely aren't on the way.
And the initial post replies, it looks like they've stalled over the last few years, but
even if it takes another 10, at least they are having discussions on them.
And Jonathan continues. we aren't. It's been discussed once in SG7 for 15 minutes,
four years ago. And then he says, quote, Herb has a tendency to give grand talks about features
the committee has never seen before and frames them as if they are the next big thing of C++,
end quote. I liked it. Jonathan doesn't hold any punches.
No, he doesn't.
Some other suggestions went like,
we need solid UTF-8 strings functions in the standard library.
It's insane to not have that in this day and age,
which is fair, but as far as I know,
some work is ongoing in that.
Software IEEE 754 decimal floats, as opposed to float floats.
So that would be good for, you know, counting money.
Binary rather than decimal, I think.
Oh yeah, yeah, yeah.
Maybe.
You're right. Yes, yes, of course.
So decimal floats would be good for counting money.
Modern cross-platform native UI library.
Well, that's not going to happen.
And someone wished for a library for mapping subclassing enums
in some way. In the absence of reflection,
most people suggested magic enum, which we use at work and it's working pretty well.
And there will be a link to a blog post explaining what is the magic behind the magic enum. And someone wished for a library like
Python's urllib for easy construction of internet URL requests. And apparently there is such
a thing. It's called CPR. And it's called C++ requests curl for people a spiritual port of python requests
and it's a wrapper around lib curl with a very nice interface which basically lets you quickly
shoot all kinds of http and other requests without too much hassle. It's very good. Looks very good.
Yeah.
If we had a little bit more time,
I was sort of going to talk about this presentation
during ACCU conference recently,
which was called C++ and Beyond Discussion.
Vittorio Romeo, Kavalin Henni,
Nico Iositisitis and Kate Gregory.
And yeah, I had many quotes from it.
It looks like I'll have to this article. It's pretty old, from 2010, but it doesn't
make it less funny. It's from the register. And here's a quote from it. Between 1969 and
1973 Ken Thompson created Unix with Dennis Ritchie.
At the same time he also developed the C language.
The speed and simplicity of C helped Unix spread widely.
Both have subsequently become quite popular.
Google hired Thompson to create a new language Go.
But Google also requires all of its recruits to pass a language test.
According to Thompson, he hasn't quite got around to it yet, and so can't submit code.
And this is a quote from the book Code Does It Work, which is like a Q&A session with
him.
I know Google has a policy where every new employee has to get checked out on languages
before they are allowed to check code in, Which means you had to get checked out on C, which you co-created.
Yeah, I haven't been. You haven't been? You're not allowed to check
in code? I'm not allowed to check in code, no. I just haven't done it. I've so far found no need to find it here. I hope you, Pjan,
didn't have to get tested on C++. Well, I haven't applied to Google.
Fair enough. I think they would be the only one. And by the way, in the bank, I never checked in code because I don't think people who aren't full-time developers doing it, clearly a lot, should check in code.
I can talk to somebody and they can help me.
But if you're not doing it on a daily basis, on a particular code base you're dealing with,
you are a bit of an amateur and you can make stupid mistakes.
Fair enough.
Maybe that's why Thomson also...
There's a certain amount of professionalism that takes experience and continuous practice.
Maybe that's why he also didn't have the need to commit any code.
But Ken doesn't feel the need to explain.
Also that.
And finally, the down-to operator, if you didn't know which is available in C++. This is a post on Mastodon from LoveGame
who says does anyone else use the C slash C++ down to operator unironically or is it
just me? And the code snippet is a while loop and there's a while parenthesis size dash dash greater than zero.
Which kind of looks like an arrow operator.
Suggesting size decreases towards zero.
If size is suitably defined by the right type, you can make that work.
I played with the star-star operator for exponentiation. It works beautifully provided the argument actually is something for which star and is defined suitably. But the point is, combinations of operators
can be made to do just about anything.
Well, that's all I have for today.
Thank you very much for coming, and I'll talk to you soon.
Bye.
Bye.
Bye.
Thank you.
Thank you.
Bye.
Thanks, Gleb.