I think that for the octagon example, you want to rotate it 360°/8 = 45°, not 30°?
Corrected, thanks for pointing that out.
I would say the problem is that they’ve tried to provide too little information to c++ operators. As mentioned, the map doesn’t know whether the item is coming or going. To name another language that doesn’t have this problem, lua clearly separates reads and writes via the __index and __newindex metamethods. (Although you can be naughty and write a mutating index.)
I wonder if this is solvable by returning a different object type, that itself implements operator= for setting and cast for getting. The actual map update would be delayed until operator= and not trigger for cast.
Scala is another example: it has .apply(k) for reads and .update(k,v) for assignment syntax. Another interesting API design is Rust: it exposes possibly-empty map entries, and provides explicit methods that specify how to handle the different cases.