5 ms·
> Actually C++ doesn't have immutable data unless you count compile-time constants and literals. You can declare things 'const', but that only provides a read-o
by searealist 9y ago
> Actually C++ doesn't have immutable data unless you count compile-time constants and literals. You can declare things 'const', but that only provides a read-only (1) view on mutable data.
const std::set<int>& s // This is a read-only view.
const std::set<int> s // This is immutable.
> Another approach is to just declare member variables 'const'. So you have a 'const map<int, int>' as a member variable. Except for that to work, you need to construct that member variable in the initializer list. The body of the constructor is too late. This likely means taking an already-initialized map as a constructor argument and copying it (probably exposing implementation details in the process) or writing a helper that returns the appropriate map type and copying it. Good optimizers will elide many or all of these copies, but relying on quality of optimizers isn't portable.
Foo() : s(helper()) {} // This is a move, not a copy.
- blub 9y agoYes, humanrebar is really grasping at straws. :) I would also mention that using mutable and const_cast is frowned upon and it can be trivially searched for and forbidden. Their comment about const iterators also misses the mark. Yes, the designers of the C++ standard library did a bit more work and now everyone has a high-quality type-safe dictionary implementation available. That's how it's supposed to work...
- humanrebar 9y ago> humanrebar is really grasping at straws. :) On the contrary, I've had to mentor a lot of C++ developers where they were surprised when their put-const-on-it approach to providing safety resulted in production bugs. I think it's fair for people to be surprised by this sort of thing. And I don't think the things Go developers have to do are all that much worse than equivalent code in C++. In C++, 'const' mostly means the compiler will give you nice diagnostic errors if you do mutable things to 'const' things. There aren't any guarantees about the data itself being unchanged. > the designers of the C++ standard library did a bit more work My point was that all container implementations need to do the same work if they want both const and non const iterators. You can't just return 'const iterator' from you 'begin' method because that implicitly converts to a non const 'iterator' and a mutable view of your container. > Yes, the designers of the C++ standard library did a bit more work and now everyone has a high-quality type-safe dictionary implementation available. I very much appreciate the hard, mostly unpaid, work that people put into the C++ standard. But everyone has to do a bit more work if they want, say, a read-only key-value store laid out in contiguous memory. The standard key-value stores are a pretty straightforward rb-tree and a suboptimal (to allow for iterator semantics) hash table. It's not hard to implement (again, due to hard work from the standard committee) a sorted vector<pair<Key, Value>>. It's a bit of arcane work, however, to make that optionally const or to have it share an interface with map and unordered_map.
- blub 9y agoContext is everything. If you come in the middle of a topic about declaring a bog-standard map and start discussing the subtleties of const, container design and the map implementation you will confound people and are frankly off-topic. :) I mean the discussion was about declaring a simple map. In that context, it really is as easy as writing const std::map<int, bool> map; Go can't do that. C++ can do that. Seems pretty straightforward.
- humanrebar 9y agoThat's basically only useful as a stack variable, though, which was my point. Well, that and "immutable" in the context of C++ is misleading. It was on topic because I am saying the C++ boilerplate wouldn't really be better than the Go boilerplate. All the "out of context" details are basically my point. You need to know a lot of surprising things to C++ well.
- geezerjay 9y ago> On the contrary, I've had to mentor a lot of C++ developers where they were surprised when their put-const-on-it approach to providing safety resulted in production bugs. Can you provide any concrete example on how adding a const qualifier introduces bugs? Besides disallowing calls to mutable member functions, adding const qualifiers changes nothing in the code.
- humanrebar 9y ago> const std::set<int> s // This is immutable. > Foo() : s(helper()) {} // This is a move, not a copy. First, I'll point out that the data of s is not immutable. The fact that you can const_cast away the const and change the value makes that clear. If people do things like that (or corrupt memory or have race conditions in the code), C++ doesn't necessarily give you clear exceptions or compiler errors. Many of the ways to break things result in "undefined behavior", which might involve data corruption and crashes. I've seen both happen to 'const' objects in production code. You have a fair point about the move. But not all projects are using C++11 yet. And your use of a 'helper()' builder was actually part of my point as well. The article complained about all the extra code needed in Go to do immutable maps. But it's not true that in C++ you can just add 'const' to a few spots and move on. I'll also point out that having the 'const' member in 'Foo' likely makes it impossible to implement assignment operators and possibly a move constructor, depending on what you are doing. It's likely if you want to have read-only semantics in your data in C++, you'll have to be aggressive using unique_ptr and shared_ptr so that you can have things like proper move semantics. And that means you'll likely need to be checking for null data. Point being, you can achieve read-only semantics in C++. But it's not foolproof and it's not as clean as the article seems to imply.
- searealist 9y agoconst std::set<int> s; // This is immutable. const_cast<std::set<int>&>(s).emplace(); // This is UB.
- humanrebar 9y agoAnd what do the assignment operators of Foo look like?
- searealist 9y agoI'm fixing your incorrect understanding of how const works in C++ and you are choosing to be argumentative.
- geezerjay 9y ago