3 ms·
It is a quirk of C++ that element lookup and assignment are forcibly unified like this. Ruby for instance has an operator[]= which could solve the problem.
by colonwqbang 4y ago
It is a quirk of C++ that element lookup and assignment are forcibly unified like this. Ruby for instance has an operator[]= which could solve the problem.
- gpderetta 4y agoYou could do it in C++ via proxy objects, but are kind of tricky to get right.
- raverbashing 4y ago"quirk" looks more like "major overlooked detail" to me I mean, left side expressions and right side expressions are different
- tialaramex 4y agoIndeed, Rust's HashMap implements Index<&T> but not IndexMut<&T> meaning you can write this: let salary = salaries["Jim Bob"]; // Note this panics if "Jim Bob" isn't a key in salaries, by analogy to arrays which panic if you do an out-of-bounds array access However you can't write this, it won't compile: salaries["Jim Bob"] += 10_000; // No raise for Jim Bob, this does not compile because that's not a mutable reference.
- deredede 4y agoTo be fair, you could achieve the same in C++ by only implementing `operator[]() const`.
- tialaramex 4y agoHuh. Does that do the same thing? I can't figure it out in my head whether this causes all the correct things to fail and everything else to work.
- deredede 4y agoIf you only implement operator[]() it should do the same thing as only implementing Index in Rust, thanks to implicit cast conversion. Whether it causes "the correct things to fail and everything else to work" is up to interpretation, as this will give you const references to the array values, which is much less idiomatic in C++ than in rust.
- tialaramex 4y agoYeah, I think this probably does what I think ought to happen here, but in the process it probably makes a bunch of reasonable looking C++ not work, and thus would make programmers unhappy which is not a good goal :/
- goalieca 4y agoC++ allows you to override the constness of everything internally by defining a member variable as `mutable`.
- plorkyeran 4y agoUnfortunately while C++ does distinguish between things which can appear on the left hand side and right hand side of assignment, the things that can go on the lhs are much broader than in most programming languages. For example, a pretty normal thing to write in C++ is `foo(map) = 1;`, where foo something like `int& foo(std::map<std::string, int>& map) { return map["key"]; }`. The ability to compute and pass around lvalue references (where "lvalues" are approximately "things that can appear on the lhs of assignment") is a very powerful feature, but also one which causes complexity in all sorts of other places, which is a bit of a theme for C++. One of those complexities is that non-const `operator[]` essentially has to be `operator[]=` even if at this specific call site there's no assignment happening. C++ could have had const `std::map:::operator[]` throw an exception if the key isn't present, but having const and non-const versions of a function do different things is extremely error-prone and instead you have to use at() if that's what you want.
- asveikau 4y agoThey're not forcibly unified if you don't use operator overloading. There is a find() and an insert(). I tend to use find() when doing a read only lookup, and operator overloading for writing.