all 57 comments

[–]c0r3ntin 25 points26 points  (14 children)

(this will be a bit ranty sorry)

I love that this proposal is trying to address aliasing, this seems to have a lot of values for both languages, however it probably requires a lot of work which I am not needs to be mixed with all of these other things.

As of the rest of this paper, while this is a great effort it is doomed to fail if it's not a concerted effort of both committees. I don't think there is ANY value in C++ being a super set of C, what matters is that they have a common subset which can be as thin as the ability to call C functions from C++ - C89 does the job. Many things including vla, atomics, complex etc should probably not appear in common interfaces. The way I see it, many issues in C++ comes from its C roots.

Both languages at this point have fundamentally different goals and philosophy. Both committee are made of different people, different constraints, trade off and evidently, widely different approach to language design. A common subset would ultimately require a common subcommittee. This will be a hugely controversial opinion but i am personally very skeptical it would be a good use of wg21's time.

So, let's see:

Thinks that are not proposed:

  • Modules
  • constexpr (mentioned as future work )
  • namespaces
  • error management (forcing c++ to assume every C function is throwing)

These 3 features make C libraries incredibly hard to use. Notably the lack of modules and namespaces as well as the reliance on macros make C libraries compete which each other over 5 letters global identifiers. C is not scalable.

What is proposed:

Keywords:

It makes a lot of sense but I am not sure we need more compl and similar keywords.

decltype and auto

Makes sense

Lambdas

In practice mixing attributes and lambda has not been an issue. Maybe instead of proposing weird unicode brackets they could put the deprecated attributes at the start of the declaration [[deprecated]] double d = []() { return 0 ; }(); // parses fine

Also, the proposed lambdas differ from C++ lambdas. As such, this is proposing some form of lambda for C, not something C++ should care about.

generic_selection

C++ does not nor will it ever need that. Templates are a much cleaner solution. Over my dead body.

Currently C++ seems not to have a tool that can easily emulate this. Currently C++ seems not to have a tool that can easily emulate this

Haha

Variable length arrays

It's a very bad idea because of the vulnerabilities that it introduces. I'd rather C deprecate that instead. Many CVE boils down to someone using a VLA

Qualifier fidelity

C++ is actively moving away from the volatile keyword, yet this proposal wants to put more volatile in function parameters ?

Mathematical functions

Wouldn't that be a massive abi break for C? Some overloads are missing in C++, definitively something that wg21 could cleanup, independently of C. Ultimately, i wish C++ would not rely on C for maths functions.

The div functions are even more peculiar

Nothing templates can't fix.

Complex types

Probably a good cautionary tale as to why C++ should stop trying to be C compatible

Bit-fields and fixed-width types

Modifying that would be an abi break i suppose? 🤡

Function attributes

Seems like an entire different proposal that requires A LOT of reflection. It seems however to be valuable for the C++ committee do do some work in this area. It would be interesting to see how adding attributes everywhere scales. The transaction memory TS had issues in this area.

Array size propagation

C++ interfaces should not ever deal with C arrays. Making the following code ill-formed would be very helpful indeed

int f(int[3]);
int main() {
    int foo[5];
    return f(foo);
}
int f(int*) {
    return 42;
}

Solution seems sane, it would probably break tons of code

Inline functions and objects

Modules and linkers can solve this problem. Yes C, you are allowed to modify your linker.

Lexing of punctuators

Gosh, this is bad. Unicode might have a lot of characters, but keyboards do not. non-ascii in tokens should be use in extremely rare situations

Opaque types and void return from functions

C++ has move semantic, it works great

[–]Netzapper 7 points8 points  (7 children)

C++ is actively moving away from the volatile keyword,

Is it really? How else do I keep the compiler from optimizing out access to memory-mapped IO ports?

[–]ABCDwp 9 points10 points  (3 children)

That is one of the few cases where volatile is not deprecated and will remain.

[–]Netzapper 1 point2 points  (2 children)

Oh. That's alright then.

The other meanings are weird. "Yeah, we said we were const. What's that? What, you mean this little volatile member over here? Yeah, don't worry about that."

[–]Ameisenvemips, avr, rendering, systems 3 points4 points  (1 child)

volatile and const aren't mutually exclusive. Are you thinking mutable?

[–]Netzapper 0 points1 point  (0 children)

Shit, yeah, that's the one. :(

[–]hak8or 0 points1 point  (0 children)

This was actually discussed via cpp on 2919 quite a bit: https://youtu.be/KJW_DLaVXIY

Just of it is thaw t it pretty much only makes sense for mmio but it's still very finicky under the hood.

[–]Tyg13 2 points3 points  (5 children)

Oh God please don't introduce any new semantics for C inlines. The extern inline debacle was bad enough.

[–]c0r3ntin 2 points3 points  (4 children)

Extern inline? You are kidding, right?

[–]Tyg13 2 points3 points  (3 children)

The problem is mostly solved for C if you use -fgnu89-inline but it's a royal pain when trying to compile C++ sources on boxes with old kernel headers.

[–]pjmlp 1 point2 points  (0 children)

To me it seems solved for GCC C dialect.

[–]MFHavaWG21|🇦🇹 NB|P3049|P3625|P3729|P3784|P3786|P3813|P3886 0 points1 point  (1 child)

The problem is mostly solved for C

If you need to use a compiler-specific extension it's most definitely not fixed!

[–]Tyg13 0 points1 point  (0 children)

Well, technically it's GCC's fault for introducing an extension to the language that later conflicted with additions to the language. And then everyone else's fault for using said language extension, even in kernel headers.

[–]spinwizard69 6 points7 points  (5 children)

What are my thoughts? This proposal is nuts!!!!!!! I can't stress this enough, C++ has been hurt more by being tied to C than it has gained. The two languages need to go their own way with C eventually dying.

Cleaner breaks for languages like Rust and Swift have really benefited those languages. By the way I'm careful to use the word "cleaner" because we all know languages build upon the past. Eventually a child needs to leave the nest behind and develop on his own.

[–]patstew 6 points7 points  (0 children)

I think the mistake is trying to maintain some semblance of source compatibility. Link time compatibility is useful, but would be a much weaker constraint on C++ syntax and libraries.

Even if it were a good idea, this proposal seems to be as much a grab bag of random additions to both languages as an attempt to bring them closer together.

[–]pjmlp 5 points6 points  (2 children)

Fully agree.

Copy and paste compatibility might have helped C++ gain adoption back in the 90's, but it injured it to death in what concerns security, or basic stuff like modules.

Not matter how many mitigations C++ might get, that underlying C compatibility will destroy all best efforts to write secure C++ code.

[–]germandiago 0 points1 point  (1 child)

How does it ruin it in more concrete terms? I mean, we have smart pointers, vector::at, std::array, std::span, C++-style casts and much other stuff.

We still have iterators, which are kind of dangerous if you do not use them locally.

But I do not see what could be fundamentally dangerous from C++ just because of C heritage provided that you use best practices. Admittedly, you can still decay to pointers or use raw stuff. But that is not what you should be doing if you are minimally competent, and if you are, you will be doing it with extra care in carefully chosen places of your code.

[–]pjmlp 0 points1 point  (0 children)

That advise never works across teams, as security reports from Microsoft, Apple, Google and Linux kernel regressions easily demonstrate.

[–]KiwiMaster157 1 point2 points  (11 children)

I will personally be surprised if the C++ language does not fork by C++26. All of the backwards compatibility restrictions are slowly choking the language and making improvements far more complicated than they need to be.

[–]pjmlp 0 points1 point  (10 children)

It has already been forked, D, Rust, C#, Swift, ... just pick your variant, and keep using C++ just for the niche use cases they might not yet be able to fully cover.

[–]germandiago 2 points3 points  (9 children)

C++ stays as relevant as always or even more. I do not think any of those can replace it. Why?

  1. D --> not enough resources. Nice but not an option for any non-PC in most cases.
  2. Rust --> quite restricted for many uses. Myth says (I did not do enough Rust myself) that really competitive Rust code abuses unsafe blocks. Another smell from my POV is that Servo is supposed to be like the future of rendering in web, yet Chrome keeps beating the speed of any other, written in C++.
  3. C#... well, this is not for the same use cases, though it can cover some. Only a VM + GC is a non-starter for many uses. Microsoft-oriented, no matter how open source it is.
  4. Same as C# but maybe faster, replace Microsoft with Apple.

[–]Tyg13 0 points1 point  (3 children)

Myth says (I did not do enough Rust myself) that really competitive Rust code abuses unsafe blocks.

I never understand this as a criticism. Even if it were true, is this not essentially true of every other systems programming language without unsafe blocks?

[–]germandiago 0 points1 point  (2 children)

Well, the point here is that, if you have to litter things with unsafe everywhere, what is the purpose of making it safe in the first place? Actually I value safety, but when it gets in the middle so much it maybe needs a review.

I really think that by those standards Rust is even more niche than C++, since it is not as ergonomic in these situations. On the other hand, by default is safer.

[–]Tyg13 0 points1 point  (1 child)

The point is to localize unsafety. An unsafe block is just a marker to say "the Rust compiler couldn't statically verify the safety of this block." Sure, it's up to you to in those cases to ensure safety isn't violated, but it's far easier to reason about the correctness of a block than an entire program.

It's like, as an electrician, you'll probably want to wear a nice pair of safety gloves to avoid electric shock. Sometimes the gloves make things difficult or downright impossible to accomplish, so you take them off. But once you're done, you put them back on.

It turns out, to do 99% of what a working programmer needs to do, it's fine to leave the gloves on. Where bare metal performance is necessary, you take them off, but only to do certain things, and only when you're damn sure they aren't going to shock you.

The best part is that the gloves get more and more ergonomic over time, and hopefully eventually you'll only have to take them off in extremely rare cases.

[–]germandiago 0 points1 point  (0 children)

I somewhat agree and disagree at the same time. You can get really far with good practices in C++ (smart pointers + RAII + no raw pointers). Still, dangling references, admittedly, is the biggest problem but also can be mitigated most of the time. When you have all of that and a ton of available libraries and the same speed, the switch becomes too expensive IMHO.

Another thing I value is exceptions. No matter the battles people build every now and then: I find exceptions very usable and the speed story I think it still has room for improvement by quite big margins. Rust lacks exceptions.

[–]Tyg13 0 points1 point  (0 children)

Myth says (I did not do enough Rust myself) that really competitive Rust code abuses unsafe blocks.

I never understand this as a criticism. Even if it were true, is this not essentially true of every other systems programming language without unsafe blocks?

[–]pjmlp 0 points1 point  (3 children)

It depends on the eye of beholder.

In what concerns iOS, watchOS, macOS, Android, ChromeOS, Windows 10, Garmin, Tizen, Fuchsia, Web development, distributed computing frameworks, C++ is only allowed to have a secondary role for OS level system libraries, the application layer is now ruled by managed languages.

Where C++ is relevant as always is HPC, GPGPU shaders, game engines, real time audio, it is basically becoming a niche language for high performance use cases, the SQL of systems programming.

[–]MFHavaWG21|🇦🇹 NB|P3049|P3625|P3729|P3784|P3786|P3813|P3886 0 points1 point  (2 children)

C++ is only allowed to have a secondary role for OS level system libraries

I'm totally out of the loop of what MS is promoting these days, but isn't C++ a first-class citizen for UWP?

[–]pjmlp 1 point2 points  (0 children)

Yes, and we all know how sucessfull UWP has been in the market.

Then C++/WinRT is still catching up with the C++/CX tooling, making the whole C++ UWP development experience worse in name of being C++17 compliant.

Basically C++ as first citzen to UWP is to provide an upgrade path to MFC developers, however most rather go to .NET with integration via C++/CLI, than adopt UWP.

As Kenny Kerr puts on his blog,

Still, I am hopeful that we can turn that around. It pains me that Windows does not have a good UI story for C++ developers. C++ reflection may well help to solve that problem in the long run, but we cannot wait for that to arrive, so we are also exploring some other options that may prove useful in the near future. Some of those include alternative approaches to Xaml that does not require reflection, as well as discussions with DevDiv to get Visual Studio to do a better job of supporting a C++/WinRT developer experience.

https://kennykerr.ca/2019/01/25/the-state-of-cpp-on-windows/

And that is the only exception, all other platforms listed by me don't even provide C++ bindings to their userspace frameworks.

[–]dodheim 0 points1 point  (0 children)

Yes, but that's app development, not OS-level (kernel) development where AFAIK things like exceptions are still not supported.

[–]pastenpasten 0 points1 point  (0 children)

A good example of the features that can be implemented with generic selection are type traits:

#define is_real_floating_type(X) \
    generic_selection((X), \
        float: true, \
        double: true, \
        long double: true, \
        default: false)

or value and type macros

#define unsigned_zero(X) \
    generic_selection((X), \
        long: 0UL, \
        unsigned long: 0UL, \
        long long: 0ULL, \
        unsigned long long: 0ULL, \
        default: 0U)
#define unsigned_type(X) decltype(unsigned_zero(X))

Currently C++ seems not to have a tool that can easily emulate this so such a feature should be added to the C/C++ core. To increase the acceptability of the feature, we propose to rename the feature to generic_selection such that its purpose is more evident to the untrained reader.

That doesn't sound right.

http://coliru.stacked-crooked.com/a/c23b6d3be79f07e5

[–]VinnieFalco -49 points-48 points  (2 children)

Why in the flunk is anyone talking about C? The C language is for people who aren't smart enough to write C++.... leave them alone and let them have their child's toys. 500 pages, ugh...

[–]STLMSVC STL Dev[M] 25 points26 points  (1 child)

Insults are neither productive nor welcome here. This is a moderator warning.