map with const keys but non const values?

后端 未结 5 662
半阙折子戏
半阙折子戏 2021-01-12 18:00

I have a situation, where I would like to have a map that does not allow to add/remove keys after initialization, but the values are allowed to change (thus I cannot simply

5条回答
  •  谎友^
    谎友^ (楼主)
    2021-01-12 18:48

    I understand that you simply want to disable the index access operator so that a user cannot accidentally add a default constructed item to the map. My solution is inspired by Chris Drew's solution but has the added benefit of remaining const correct (i.e. not allowing changing values of the map when the map is const).

    Essentially, by disabling default construction you remove the ability to invoke the index access operator provided by std::map. The other methods will remain available since std::map is a class template and member functions won't be evaluated until they are invoked. Hence, std::map::at will work fine but std::map::operator[] will result in a compile-time error.

    Inspired by Chris you can use a wrapper on the mapped_type to disable default construction. I took his demo and tweaked it a bit to demonstrate how to disable default construction and used it with std::map rather than a const std::map.

    template
    class RemoveDefaultConstruction {
       T value;
    public:
       RemoveDefaultConstruction() = delete; // The magic is here
        RemoveDefaultConstruction(const RemoveDefaultConstruction &other) noexcept(std::is_nothrow_copy_constructible::value) = default;
        RemoveDefaultConstruction(RemoveDefaultConstruction &&other) noexcept(std::is_nothrow_move_constructible::value) = default;
        RemoveDefaultConstruction(T &&t) noexcept(std::is_nothrow_constructible(t))>::value) :
        value{std::forward(t)} {
        }
    
        RemoveDefaultConstruction& operator=(const RemoveDefaultConstruction &other) = default;
        RemoveDefaultConstruction& operator=(RemoveDefaultConstruction &&other) = default;
        RemoveDefaultConstruction& operator=(T &&other) { value = std::move(other); return *this; }
        RemoveDefaultConstruction& operator=(T const &other) { value = other; return *this; }
    
        T const &get() const { return value; } // Keep const correctness
        T &get() { return value; } // Keep const correctness
    };
    
    void update(std::map> &m, int k, int v) { m.at(k) = v; }
    void update(std::map> const &m, int k, int v) {
       //m.at(k) = v; // ERROR: Cannot change a const value
    }
    

    Live Demo

提交回复
热议问题