5 ms·
Better question: why did C and C++ not define this as left to right (the answer is perf claims decades ago, that are not really valid now, and questionable even
by olliej 4y ago
Better question: why did C and C++ not define this as left to right (the answer is perf claims decades ago, that are not really valid now, and questionable even then).
The example
a[b]
doesn't really exhibit the unexpected, but as I understand it
f()->a[b()]
could evaluate as
temp = b()
f()->a[temp]
which it seems reasonable to consider unexpected. The lack of left to right sequencing here seems not-dissimilar to the lack of sequencing in call arguments, which was also realized to be a needless footgun and fixed.
- TremendousJudge 4y agoHalf of the new features of "modern" C++ editions leave me agreeing with the change but wondering what they were thinking before. Another example: std::map::contains was introduced in C++20; why did they go decades thinking it wasn't necessary to have such an operator (instead providing only count() even though a map has unique keys), and why did they change their minds only now? Did the old guard literally die off or something?
- olliej 4y agoThe historical lack of sequencing is because they were unsequenced in C, and C++ thus inherited it. And yes, it does seem that there were a lot more people hell bent on resisting correcting unnecessary UB in the past than today, but they’re still around.
- TremendousJudge 4y agoI get it, but then, why change it now? (or 6 years ago I guess)
- olliej 4y agoSorry, I had an unsaved edit above. It seems the resistance to removing unnecessary UB has reduced over the years.
- PaulDavisThe1st 4y agostd::map::find (item) != map.end() <=> std::map::contain (item)
- zimpenfish 4y agoI think the problem is that with `std::map::find(item)` you get the value back but you don't with `std::map::contain(item)` - which means a second lookup to actually retrieve the value, no?
- tubs 4y agoProblem with contains is we are now going to see more code like if (map.contains(foo)) { bob(map[foo]); } over the (vastly uglier) more efficient: if (auto it = map.find(foo); it != map.end()) { bob(*it); } Of course languages like C# manage this in a more elegant way with out parameters declarable at the call site.
- JonChesterfield 4y agoA pity the c++ compiler has no way to recognise calls to the c++ library in order to do rewrites like that automatically. It's CSE at the stdlib level, should definitely be possible to do that.
- eklitzke 4y agoHard coding behavior like for the STL that seems pretty questionable, especially given that std::map and std::unordered_map have poor performance compared to other alternatives (e.g. absl::btree_map and absl::flat_hash_map, and likewise folly has better implementations).
- im3w1l 4y agoif let is such a nice way to express this if let Some(x) = map.get(foo) { bob(x) } One subtle but noteworthy thing is that the idiom only mentions map by name once, which is nice if you have a very long map name, and prevents copy paste bugs where you only update one of the two mentions.
- olliej 4y agoThis pattern exists in C++ as well. The specific issue here is that all these STL APIs are in terms of C++'s iterator model, and can't be replaced with a more modern "optional" style that allows this cleaner coding style :-/
- paulddraper 4y agoScala: for (x <- map.get(foo)) { bob(x) } // or map.get(foo).foreach(bob) // or map.get(foo) match { case Some(x) => bob(x) }
- deleted 4y ago[deleted]