Like having C structs magically turn into C++ ones, thus implicit rules like these.
Anyone that cares about C++ evolution should read "Design and Evolution of C++", not only for how it came to be, also for safety approaches over plain C, that Bjarne is stil arguing for to this day on WG21 meetings.
For example, the following code does not compile with either -std=c89 or -std=c++98, but does compile if we uncomment the constructor line:
struct Foo {
int x;
/*public: Foo(int x) : x(x) {}*/
};
int main() {
struct Foo foo = 5;
return 0;
}
$ gcc -std=c89 tmp.c
tmp.c: In function ‘main’:
tmp.c:8:20: error: invalid initializer
8 | struct Foo foo = 5;
| ^
$ g++ -std=c++98 tmp.c
tmp.c: In function ‘int main()’:
tmp.c:8:20: error: conversion from ‘int’ to non-scalar
type ‘Foo’ requested
8 | struct Foo foo = 5;
Maybe I'm missing something?Additionally, you are missing the whole package of struct semantics in C++, that while they should at naked eye still look like C structs, they have to also support C++ struct semantics, of memory construction, copy assignment and bitwise comparisaion.
Hence why structs and classes are the same, with the difference that structs are public by default, with code generated for keeping the bitwise C semantics, until any of those operations are redifined, at which point the compiler leaves out the job to the developer.
It seems like an unforced error in the language design, rather than a concession to backwards-compatibility.
Except for the captured variables in a lambda which are const unless you use the mutable keyword. Not a bad idea though.
Is there a way to force capture by const-reference by the way?
int main() {
int x = 0;
[&x] { x= 1;}(); // works
[&x=std::as_const(x)] { x= 1;}(); // error: assignment of read-only reference 'x'
}
Not very pretty, but it works.