I think this glances over what structs actually are in C++, and unwittingly portrays them as something different.
Structs in C++ are definitely exact like structs in C. Or they can be, if that's what you're aiming for. If you include a C header file that defines a struct in a C++ program, you build it, and you use instances of that struct to pass them to C programs, everthing just works.
The detail you need to be mindful of is that C structs support a subset of all the features supported by C++ classes, and once you start to use those features C++ also allows implementations to forego some constraints.
If you expect to use a struct in C++ but still define it in a way that you make it include features that are not supported in C then you can't pin that on the language.
https://learn.microsoft.com/en-us/cpp/cpp/trivial-standard-l...
Using C-like structs is a very common use case, to the point that the standard explicitly defines the concept of standard layout and builds upon that to specify the concept of a standard layout type. A struct/class that is a standard layout type, which means it's a POD type, corresponds exactly with C structs. They are explicitly defined in terms of retaining interoperability with other languages.
Still. There's always extern "c".
But yes, if you make extra sure (under threat of footgun) that your struct only has simple types in it and doesn't use virtual or define any ctors/dtors or use protected/private or use inheritance and all of its members follow those rules etc etc, maybe you can treat it like a C struct. But the C++ Standard is telling a different story.
Keep in mind, I'm not blaming you for ignoring all these complications if at the end of the day the compiler seems to give you the behavior you expect. But the fun of C++ is that it's kind of two programming languages in one: the language the Standard defines, and the language the typical programmer thinks it is.
[0] There was std::is_pod, but it was deprecated because it doesn't reflect how the Standard actually defines things. A bit of a cruel joke, dangling that in front of us and then yanking it away.
References:
1) Trivial, standard-layout, POD, and literal types - https://learn.microsoft.com/en-us/cpp/cpp/trivial-standard-l...
2) No more plain old data - https://mariusbancila.ro/blog/2020/08/10/no-more-plain-old-d...
Keep in mind, my original comment was pretty much just drawing a line through TFA, which also argues that you can't cleanly map C++ object concepts onto C structs. C++ has some backwards compatibility with C obviously but nowadays it's a totally separate language with an independent standards body (for better or worse). Specifying "do what C does" might have flown in 1998 but that changed a long time ago.
I am fully with Stroustrup in arguing that C++ should strive for as much compatibility with C as possible in the spirit of the original (see ref. at https://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B...). But sadly the rest of standards committee don't seem to want this which i believe is a huge mistake. On the other side, the C standards committee should be very careful what inspiration they take from C++ in the evolution of the language since it was designed as a "minimal" language which was one of the main factors in its success. Whether people call it "primitive", "well behind other languages" etc. does not matter. You definitely don't want C turning into C++-lite. Hence IMO the conclusions stated in the last few paragraphs of the submitted article are quite right.
In a way, the whole C++ endeavor was doomed from the start. C was old and pragmatic and vague, a "portable assembly", and it was a shaky foundation to build C++ on top of. When the Standard tried to tighten things up, it just got more lopsided, full of hacks to fix hacks. But the alternate universe where C++ had a more pragmatic, laissez-faire design going forward probably isn't any better; maybe the "standard" would have become "do whatever GCC does"--or in the Darkest Timeline, "do whatever MSVC does".
I disagree that C++ "respecting its C roots" is viable. The C++11 and later Standards were trying to make the best of a bad situation, and that required leaving C behind because the C way of doing things doesn't fit with a higher-level language like contemporary C++. Especially when the language has multiple implementations that need to compile the same code the same way. The "C with classes" days are long over for most of us who have to use libraries expecting std::vector, smart pointers, and exception handling. We live in mortal fear of compiler writers smiting us for innocent things like punning through a union.
> You definitely don't want C turning into C++-lite
I agree. Trying to quickly hack classes or templates or whatever back on top of C would just start the whole C++ nightmare over again.
Hey! Them's fighting words! :-) "C++ as a better C" (which is what it started as) was/is/always will be needed and necessary. It gave you the best of both low-level and high-level worlds with full control and just enough complexity. Instead of implementing structs full of function pointers to design dynamic dispatch object models you just had the compiler do that for you while still retaining full control over other aspects. I still have some manuals that came with SCO Unix one of which was on the then newfangled C++ language. It had one chapter by Stroustrup himself (his original paper probably) on the C++ object model showing how vptrs/vtables are implemented and thinking it neat that the compiler did it for you. Also templates were just glorified macros then with none of the shenanigans that you see today. Hence moving from C to C++ was easy and its usage and popularity exploded. But with the infusion of lots of people into C++ land people who were not aware of the original vision/design/compatibility goal of the language started asking for the inclusion of more and more OO and modern language features. The result? The standards committee reinventing the language from C++11 onwards(and changing every freaking 3 years) and alienating the old C++ folks who made it popular in the first place. No doubt there are some benefits like increased design space and modern programming techniques but am not sure whether the increased complexity makes it all worth it. For me it is still C++98 with the addition of the STL and some simple generic programming techniques which is the sweet spot.
C++20 introduced `std::bitcast`, so I appreciate alias analysis getting all the help it can.
Not true. Using C structs themselves in C++ is very common - when you include the C header file, the relevant declarations are wrapped in "extern "C" {}" which gives structs C semantics. You can do this because C++ is backwards compatible with C.
Most of the time when you use a struct in C++ you're just ignoring most of the capabilities of objects (which is fine!). If you declare a struct in C++, you're getting an object. The only difference between the struct and class keywords in C++ is the default privacy of the members.
What I think you're trying to say is "a POD structure with no custom behavior is essentially identical in C and C++". That is mostly true, though if the struct contains a union, C++ has stricter UB rules (there might be other differences as well, but that's the one I can think of at the moment).
100% of the using structs like they are C structs vs using class as objects is cultural not a part of the language.
C++ is somewhat unique in that it started out as a few extra features on top of C before gradually splitting off and mutating into a totally separate programming language.
But Cfront was released circa 1983 and you basically just wrote C, but it added a bit of new syntax that generated extra C behind the scenes. Object-oriented programming was still fetal in 1983! It didn't get really hyped until the mid-90's. So C++ kind of mutated for decades as this gross appendage on C until it became this whole separate blob that ate half of programming. It was 15 years later when the C++98 "standard" started trying to reign in Dr. Stroustrup's monster.
Then in 2005 we threw away all our textbooks that were like "Look! `Apple` derives from `Fruit`! `Car` derives from `Engine`! This is going to change the world!" because adding object-orientedness to everything became uncool when our bosses became fans of Java. But by this point the C++ blob had taken on a life of its own...
So yeah. Very few programming languages have a story as long and insane as C++.
Objective-C++ likewise on top of CFront.
Until like with CFront, they became selfhosted compilers.
Groovy code is Java code, regardless of targeting the JVM, the same syntax is supported and extended with dynamic capabilities.
Object Pascal was created for Lisa project, exactly in 1983.
Tom Love and Brad Cox created Objective-C in 1984.
I think this take is completely wrong. There is nothing cultural about it. C++ was created as a strict superset of C, and thus from the inception it supported all features made available in C. This design goal remains true up to this day, and only started to diverge relatively recently when C was updated to include features that were not supported (yet) by C++.
When someone declares a plain old struct in C++, they are declaring a struct that is perfectly compatible and interoperable with C. This is by design. From the inception.
Just asking, for a friend.
Just a friendly reminder that two leading underscores wont protect your member functions in C++. Even if people insist that those are totally not supposed to be private in python.
Whenever I say "I'm no longer attached to all that private stuff", people always reply, "wait until you work on a large code base". I work on a million line+ code base. Whatever.
This argument aside, I'm not a total philistine. RAII is awesome but C++ is full to the boot with crusty stuff to keep the compatibility. I always feel there is a language better than anything trying to come out.
These days I'm for minimalism, most of my structs are aggregates of public members, but sometimes you really want to make sure to maintain the invariant that your array pointer and your size field are in sync.
Of course neither double nor single underscore will stop anyone who wants to touch your privates badly enough. Which is big part of the python philosophy: You're not stopped from doing inadvisable things. Instead there's a strong culture around writing "pythonic" code, which largely avoids these pitfalls.
In python, if any of this gives you an trouble you can just replace the stuff in the class dict with your own functions. You don't even need to cast.
This is not really the case. See https://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B for a non-exhaustive list.
It is true that both sides agree that compatibility is an important goal, but it's only a goal, not something that's 100% the case.