Again, "traditionally", one could (ab)use C++ as "C with extras". And it wasn't uncommon, especially in resource constraint usecases, to do just that. C++ without STL or templates, or even C++ without new/delete.
This "is not C++", agree. Would a subset be enough for "using it like C-with-RAII" ?
Given the details and pitfalls the original author lists, I suspect not. It's not just C programmers who "do strange things" and make odd choices. The language itself though "lends itself to that". I've (had to) write code that sometimes-alloca'ed sometimes-malloc'ed the same thing and then "tagged" it to indicate whether it needed free() or "just" the implied drop. Another rather common antipattern is "generic embedded payloads" - the struct definition ending "char data[1]" just to be padded out by whatever creates it to whatever size (nevermind type) of that data.
Can you write _new_ C code that "does RAII" ? Probably. Just rewrite it in rust, or zig :-) Can you somehow transmogrify language, compiler, standard lib so that you can recompile existing C code, it not to "just get RAII" then at least to give you meaningful compiler errors/warnings that tell you how to change it ? I won't put money on that.
https://www.youtube.com/watch?v=rX0ItVEVjHc
A classic which touches on such stuff.
You can do "manual" goto-based RAII in C, and it has been done for decades. The end of your function needs to have a cascading layer of labels, undoing what has been done before:
if (!(x = create_x())) {
goto cleanup;
}
if (!(y = create_y())) {
goto cleanup_x;
}
if (!(z = create_z())) {
goto cleanup_y;
}
do_something(x, y, z);
cleanup_z:
destroy_z(z);
cleanup_y:
destroy_y(y);
cleanup_x:
destroy_x(x);
cleanup:
return;
It just takes more discipline and is more error-prone maintenance-wise.Like C, with its many hidden behaviors?
I would argue that if it needs to be spelled out in a separate document from the code you're reading, then it's hidden.
It’s not clear if you’re talking about defer or RAII