Hacker News
points by drivebyhooting 4 days ago | 0 comments
Your comment just made me realize contracts is different from concepts (which are basically bounded genetics, right…?)
[–] jandrewrogers 4 days ago
C++ concepts evaluate the properties of types at compile-time. You can inject arbitrary constraints on type properties anywhere in the code including conditional codegen. It is a way of asking if a type “can express this complex set of abstract things or has this enumerated set of properties” with almost arbitrary detail. They are extremely powerful in terms of expressiveness and specialization of code. Insanely good for performance and reliability engineering.

One of the best features to be added to C++ in many years.

C++ contracts are an attempt to bring C asserts into the C++ age. The weakness of C++ contracts is that they are mostly syntactic sugar over C asserts. If you really care about this type of thing, you probably already have a custom C++ assertion framework that is at least as capable if not more.

The promise of C++ contracts is that they can aid formal verification, which would be great. As delivered, it can’t do much more than was already possible, which will inhibit adoption.

[–] amluto 4 days ago
I maintain a codebase that I’ve migrated from C++98 to C++11 and all the way to C++23 and even a bit of draft 26 (the latter for some minor library improvements). Few things made me quite as happy as moving from using SFINAE to using requires clauses and concepts.

(IMO the single best improvements over the years have been atomics and maybe variadic templates.)

[–] jandrewrogers 4 days ago
I think you are right to position atomics and variadic templates as among the most consequential features of C++ in the last couple decades. It made an enormous number of things possible.

One thing I give the C++ feature gods credit for is recognizing material deficiencies in systems languages and unapologetically trying to fill those gaps starting with C++11. The addition of atomics, strict variadics, constexpr, lambdas, concepts, lifetime annotations, etc has been transformative for C++.

[–] aw1621107 3 days ago
> lifetime annotations

Say what!?

[–] throwaway2037 4 days ago

    > the single best improvements over the years have been atomics...
Of course, libatomic and friends have existed for a long time. Real question: Do you feel that the standardisation of atomics within the C++ base library is a material advantage over using libatomic? Also, maybe there are atomic APIs in the C++ base library that are better than libatomic. If so, please kindly share an example or two. I would like to learn more.

EDIT

I forgot to give a hat tip to your big upgrade from C++98 to C++23. In some projects, that can require an enormous amount of effort! Can you share a "stories from the trenches" that were difficult in that upgrade?

[–] bluGill 4 days ago
Standards work best when they can take a bunch of existing slightly different implementations and pick the best of them all, with input from people who understand the compromises, and with input from the real world experience of the different ways those compromises work out in the real world.

Atomics could work that way. However many other things cannot - we knew modules were a good idea, but they are a everything on a project must use them before anyone can benefit and so they were forever doomed to not be in widespread use until there is a standard. Even today we see adoption is slow because while there is a standard that works everybody is waiting on some other part to adopt before they can get any benefit. (and those who need to go first see the least benefit), but there are signs that things are moving.

[–] pocksuppet 4 days ago
libatomic is a GCC implementation detail that implements atomic math operations that are not available on the target platform by using non-atomic math and compare-exchange. Are you sure that's the one you mean?
[–] Shorel 4 days ago
I want to read your blog describing these experiences.
[–] AlotOfReading 4 days ago

    The weakness of C++ contracts is that they are mostly syntactic sugar over C asserts. 
The sugar is actually one of my issues with them. The evaluation semantics are much more complicated / potentially slower than C asserts because of the sugar, and why you would have to pay those costs isn't obvious at first glance. Lisa Lippincott's excellent talk on the design of contracts [0] is what switched me from a sort of neutral support to disliking it. I think it's a stupid place for the national bodies to draw the line though. std::regex is acceptable, but a nothingburger like contracts tanks the vote?

[0] https://www.youtube.com/watch?v=yhhSW-FSWkE

[–] jandrewrogers 4 days ago
To be clear, I have a lot of issues with the contracts proposal. I probably wouldn’t use despite living out on the standards frontier. I don’t even use C asserts already because they are not expressive enough in important ways. This proposal kind of reifies the inadequacies.

I think the risk is that C++ contracts become an evolutionary dead-end that hang around forever in code bases because they were standardized. It wouldn’t be the first time this has happened.

[–] randomNumber7 4 days ago
What do you do instead of C asserts? Throwing exceptions?
[–] stingraycharles 4 days ago
Concepts are evaluated compile time and make a lot of TMP more elegant. Contracts are runtime check, akin to assertions.

Phrased differently, contracts are to concepts what assert is to static_assert.

[–] rerdavies 4 days ago
I think the wumpus that's being chased is that contracts COULD evolve into a compile time check. I'd be much happier if they actually caught the wumpus before they start polluting the language with yet another baroquely complicated feature that gets abandoned before it actually becomes useful (e.g. coroutines, and modules). Or just keep it simple and give us a C++-sensible replacement for assert(), and avoid the rest of it. i.e. contract_assert without the word "contract" in it. That would be a nice feature.
[–] bluGill 4 days ago
Today the compiler is allowed to fail to compile any code that will break a contract. However the details of what this means is very complex, and the ability of compilers to detect things that break the contract at still evolving. Thus forcing anything on a compiler would force an easy subset on the compilers while shutting down innovation in what we can do in the future.
[–] MFHava 4 days ago
Funny how often I read online that Coroutines are abandoned/useless, yet we ship products based on them and their application in our codebases grows continuously...
[–] rerdavies 3 days ago
Sure. But you would have had to use either a 3rd party coroutine library, or have written one yourselves to use coroutines.

C++20 provides the language feature only, and none of the libraries to use the feature. You can write your own library to use the C++20 feature, but the standard APIs are raw and brutally complex. There are 3rd party libraries to use coroutines, but they are not part of the C++20 standard.

C++23 provides a std::generator, which is indeed a great feature.

Finally, C++26 provides std::execution, and std::task, which finally makes the feature usable with only standard C++ feature, and provides facilities for executing coroutines on thread pools, or message pumps. Significant features and problems have been deferred to C++29.

I guess it's a fair point that coroutines have not been abandoned. But it's alarming that it will now take the better part of a decade for the feature to reach a sensible state (depending on how C++26 gets handled).

[–] MFHava 2 days ago
> You can write your own library to use the C++20 feature, but the standard APIs are raw and brutally complex.

I wouldn't put it that way, but I've written several coroutine wrapper types at this point, so my perspective is certainly not objective here.

> Finally, C++26 provides std::execution, and std::task, which finally makes the feature usable with only standard C++ feature, and provides facilities for executing coroutines on thread pools, or message pumps. Significant features and problems have been deferred to C++29.

I remain unconvinced mere mortals will use std::execution.

It's a marvellous example of proving what is possible with TMP without needing language support.

Naturally, it's template hell - heck, the main designer even wrote a Visual Studio Extension to understand the cryptic error messages it can generate.

Apart from that: it interacts badly with Coroutines. Even though the author of std::execution::task reached quite a good design (there are some warts, some of which could only be fixed by delaying to C++29 as it needed a change to the language feature), std::execution has poor support for it - which is unsurprising as key features of coroutines (like symmetric transfer) are not even discussed in P2300...

[–] rerdavies 2 days ago
That's disappointing. :-( Fwiw, as I remember it, the message pump implementation was easy enough. presumably because it doesn't require symmetric transfers. The thread pool implementation was hell.
[–] MFHava 2 days ago
Maybe I'm too pessimistic.

WG21 could realistically fix some issues as DRs before S/R is even implemented (and marked stable) anywhere (they have done so before for other features - notably std::format).

Thanks to the C++29 fix you could even remove hacks like `co_yield execution::with_error` as a non-exception-based abort-mechanism inside task.

But ... the problem with symmetric transfer is deeply rooted in the design of std::execution and would require large surgery ...

[–] mikepurvis 4 days ago
Too bad it couldn't have been contract and static_contract.
[–] YuechenLi 4 days ago
A concept is a compile time requirement that bounds templates which are the generics in C++, so you are close.
[–] rramadass 4 days ago
Concepts are for Types at compile time while Contracts are for Values at runtime.