Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way in C++ to pass a map where the structure is immutable but the values are mutable?

If a std::map is const, then its values are constant too. For example, I can't do this

void EditValue(const std::map<std::string, std::string>& m) {
  std::string& value = m.at("mykey");  // <-- compile error
  value.append("suffix");
}

But I could do this:

void EditValue(const std::map<std::string, std::string*>& m) {
  std::string* value = m.at("mykey");
  value->append("suffix");  // <-- this is fine
}

Is there no way to pass a non-pointer map and have only the values be mutable?

like image 715
Robert Martin Avatar asked Oct 15 '25 04:10

Robert Martin


1 Answers

Is there no way to pass a non-pointer map and have only the values be mutable?

If the signature is fixed to be

void EditValue(const std::map<std::string, std::string>& m);

then, no, not without a const_cast inside the function, which is not under your control if I understand your comments correctly. It's also unsafe since you must not modify an object declared const and the function has no way of knowing if it is.


Otherwise, you could create a wrapper class template for this special scenario. Inside it, you'll keep a mutable instance of your map and provide accessors just like the normal std::map but with the exception that functions returning a T& can be const qualified - so you only need one at for example.

Example:

template <class Key, class T>
class map_mutable_values {
public:
    template <class K>
    T& at(const K& key) const { // const qualified but returns non-const T&
        return m_data.at(key);
    }

    template <class... Args>
    auto emplace(Args&&... args) {
        return m_data.emplace(std::forward<Args>(args)...);
    }

    // add the rest of the member functions you want

private:
    mutable std::map<Key, T> m_data; // note: mutable
};

This would now work:

void EditValue(const map_mutable_values<std::string, std::string>& m) {
    std::string& value = m.at("mykey");  // <-- compiles fine
    value.append("suffix");

    // m.emplace("Hello", "world"); // error, m is const
}
like image 73
Ted Lyngmo Avatar answered Oct 17 '25 18:10

Ted Lyngmo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!