Yup, it's definitely a bit of a code smell if you do. The issue is more the reverse, though - I can't make a mutable map, then hand it by pointer/reference to something that says it wants an immutable map later.
That only matters if you're storing it. The big issue is 99% of code out there uses mutable template types for containers, and if you ever declare a container that doesn't have a mutable template type, you stub your toe as your new container isn't compatible with anyone else's code. You can't even easily copy your way out.
std::unordered_map<std::string, const std::string> m;
m["foo"] = "bar";
std::unordered_map<std::string, std::string> m2 = m;
Or if you (or something you call) mutate it trough another reference/pointer. Sometimes I wish there was a stronger const where the compiler (and programmer) could actually assume the object is not mutated while that reference/pointer is alive. Of course checking that is no longer doable with just the type system.
> You can't even easily copy your way out.
That depends on the type. std::unordered_maps could provide a copy constructor that does the conversion.
And you can do the copy via iterators, although that is probably not as efficient as it could be because it needs to re-hash the keys.
No, the primary point of a const cast is "I need to pass this to an API that expects a non-const pointer even though it won't mutate it".
Casting const away and then mutating is a footgun as you are in undefined behavior territory as soon as your pointer/reference is not just const itself but points to a const variable.
That seems like a good thing. If you're handed a map to const values you can't just go "imma gunna mutate them anyway".