I understand that you just want to disable the index access operator so that the user cannot accidentally add the default element to the map. My solution is inspired by the decision of Chris Drew, but it has an additional advantage over the rest of the constant (i.e. it does not allow changing the values ββof the map when the map is a constant).
Essentially, by disabling the default construct, you remove the ability to invoke the index access operator provided by std::map . The remaining methods will remain available, since std::map is the class template, and member functions will not be evaluated until they are called. Therefore, std::map::at will work fine, but std::map::operator[] will result in a compile-time error.
Inspired by Chris, you can use the shell on mapped_type to disable the default build. I took his demo and modified it a bit to demonstrate how to disable the default build and use it with std::map , not const std::map .
template<typename T> class RemoveDefaultConstruction { T value; public: RemoveDefaultConstruction() = delete; // The magic is here RemoveDefaultConstruction(const RemoveDefaultConstruction &other) noexcept(std::is_nothrow_copy_constructible<T>::value) = default; RemoveDefaultConstruction(RemoveDefaultConstruction &&other) noexcept(std::is_nothrow_move_constructible<T>::value) = default; RemoveDefaultConstruction(T &&t) noexcept(std::is_nothrow_constructible<T, decltype(std::forward<T>(t))>::value) : value{std::forward<T>(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<int, RemoveDefaultConstruction<int>> &m, int k, int v) { m.at(k) = v; } void update(std::map<int, RemoveDefaultConstruction<int>> const &m, int k, int v) { //m.at(k) = v; // ERROR: Cannot change a const value }
Live demo
source share