Hacker News new | ask | show | jobs
by pmr_ 4584 days ago
Constness is a really useful concept especially since it has been extended to also mean thread-safe (at least in the standard library), but has a bunch of design flaws that make it very difficult to use correctly.

1. It is not the default. Everything should be const by default and should be marked mutable when necessary. This even seems to be consensus in the committee and has been done for newer language features (lambdas).

2. It is not "deep" when pointers are used. This one is actually inherited by C, but still is really painful. This is fixed in D.

3. const_cast is legal C++ in most circumstances (the only exception being an object declared const). This invalidates most assumptions optimizing compilers could possibly make and takes away a lot of usefulness because there is always someone that is going to const_cast stuff around.

4. It becomes very hard to use with polymorphic types, because const-ness is part of the function signature and affects override behavior. Can you really safely say something about const-ness and thread-safety of all classes you could possibly derive? I often find I cannot and when I really need runtime polymorphism I will usually end up with lots of const-less member function.

1 comments

1. Agreed.

2. Agreed. I like D, or I want to anyway. Main problem is the garbage collector; I'm writing a game that I want to port to mobile and I don't really trust a garbage collector in a low-perf environment. Rust is sort of interesting for that reason but is a few years from being mature enough to consider I think.

3. Also agreed for projects in the large, but for the most part I write C++ for me (for an idea of the project size, my utility game library is ~14KLOC over about 200 compilation units, the game will probably be around half of both) is all my code and so I have certain assurances. The only one I'd be hurting is me. And I am averse to that. =)

4. This I'm not really so sure about. I have never really run into this issue - my base classes are generally close to all-virtual whenever possible and only expose a fairly limited set of methods. I have run into what you describe--the deepest nesting of polymorphism I have is my current project is in my drawing code, where a DrawSource is basically a time -> (rect, textureID) mapping and a Sprite is a timekeeper for DrawSource that performs a little matrix manipulation before invocation and has a list of child Sprites. I solved this by pulling everything I didn't need out of Sprite entirely and presenting a very simple interface. (I'm liberated a bit in that this is all my code, though, so I generally know what types I have bouncing around.)

In any case, I'll take flawed C++ const over "new ImmutableCollectionBecauseWeDontHaveConst<T>(someList)" when I can. I like Scala quite a bit but this mutable/immutable division drives me up the wall.