5 ms·
As someone who writes a lot of C-like-C++ (system software, network daemons), I absolutely disagree. Using a template or a destructor here and there allows you
by SomeoneFromCA 6y ago
As someone who writes a lot of C-like-C++ (system software, network daemons), I absolutely disagree. Using a template or a destructor here and there allows you write C++ code, which is as fast pure C, safer, and easily understandable to a C programmer.
- de_watcher 6y agoUse from C++ just function templates, constants and stricter conversion rules - and you've got a perfect C.
- dysoco 6y agoSadly that way it's just too easy to start using more modern solutions bit by bit and suddenly you are in object-oriented hell or worse. Sometimes I've found that it's just easier to stick with plain C that way you don't ever feel tempted.
- rwmj 6y agoA bunch of modern C programs on Linux are now using __attribute__((cleanup)) which gives you nice cleanups/destructors. You can't compile a modern Linux distro without GCC/Clang support for this attribute.
- pjmlp 6y agoAnd unportable code stuck to GCC C. How ironic that commercial vendors get crucified for C and C++ language extensions.
- SomeoneFromCA 6y agoIt is not even close in terms of functionality to some C++ constructions that emulate Java/C# "finally". Although they are considered "non-canonical" by the C++ purists, I use them often, with great success.
- jstimpfle 6y agoI doubt it's really safer at that point. You could use a few vectors or other container objects, which is a tradeoff - it gets a little bit more comfortable to spot/debug OOB issues (but valgrind and sorts can also help with the occasional problem). In exchange you are required to structure your data and code in a particular way to use these structures, which is a drawback. Another drawback is slower compile times (significantly so with std:: containers -- don't have a lot of experience with hand rolling C++ abstractions). I often prefer having globally allocated (dynamic) arrays, which are unproblematic with respect to OOB or memory/allocation safety. I use a simple macro to wrap allocation of arrays to remove the boilerplate. It becomes like "realloc_array(pptr, FooType, 42)" or even "realloc_array(pptr, 42)". Local allocations are more often not easily dealt with using Memory Arenas, which is superior to alloc/free in constructors/destructor. I even prefer using plain pointers with separate size variables for dynamic arrays. That's because "size :: array" isn't a 1::1 relationship. More than 50% of the time, I have more than one array that applies to the same size variable. Sometimes, there are multiple index/size pairs that apply to a single (or multiple) arrays. I prefer staying with C because it keeps me focused. Sure, sometimes I wish for the occasional fancy feature, but then taking the time to think about a clean approach that solves the problem with limited features often benefits code quality and readability.
- jcelerier 6y ago> I doubt it's really safer at that point. the number of bugs that the compiler has saved me by e.g. having a simple Id<T> type tag instead of ints as used by every C library under the sun is absurd.
- jstimpfle 6y agoI don't know, I've tried approaches like that, even played with writing a few C++ helper functions, and even started a compiler with the goal of exploring ideas like this. How do you go about Id<T>? The way I see that something like this can work out and give small advantages is that T would be an abstract type (a phantom or tag type, or whatever C++ guys are calling it). And all arrays that are meant to be indexed using Id<T> (while the array element types could be whatever) would depend on this type and have to be implemented using a special wrapped array type with overloaded operator[]. I don't know, this might come with many disadvantages. All the stuff goes out the roof when you're now dealing with start indices + slices, i.e. doing "pointer" arithmetics. My general feeling is that this Id<T> approach might show problems similar to the idea of using typed units, like wanting to prevent the expression "1W + 3s" but then making it terribly cumbersome to do real work, e.g. "1W * 3s" which would be perfectly valid. In one C project I resorted to using about 20-30 typedefs like: typedef int Expr; typedef int Symbol; etc. And I used these typedef names in function signatures. Variables also were named like expr, parentExpr, symbol, etc. It worked wonderfully. I had maybe 1 mistake where I submitted the wrong "type" in 6 months. And I'm someone who makes a lot of stupid mistakes.