Why can I pass the key to std :: map to a function that expects non-const?

According to the std::map

documentation , it stores key-value pairs in std::pair<const Key, Value>

, so the keys in the map are constants.

Now, imagine I have std::map

where the keys are pointers to some objects.

struct S {};
struct Data {};
using MyMap = std::map<S*, Data>;

      

Let's also assume that there is a function foo

that takes a parameter S*

.

void foo(S* ptr) { /* modify the object (*ptr) */ }

      

Now the question is, when I iterate MyMap

with a for-loop, I can pass the key of the map element to foo

:

MyMap m = getMyMapSomehow();
for (auto elem : m)
{
    static_assert(std::is_const<decltype(elem.first)>::value, "Supposed to be `const S*`");
    foo(elem.first); // why does it compile?
}

      

So, while mine static_assert

succeeds (so I'm assuming the type elem.first

is equal const S*

), the call foo

compiles in order and so it looks like I can change the object behind the constant pointer.

Why can I do this?

PS Here's a live example at Coliru that illustrates my point. For brevity, I use int

instead of S

and Data

.

+3


source to share


3 answers


so I assume the type elem.first

isconst S*



Not. The key stored in map

is equal const

, which means the std::map<S*, Data>

key will be S* const

(i.e. the const

pointer), not const S*

(i.e. the pointer to const

). Therefore, to pass it to foo(S* ptr)

, the pointer itself const

will be copied into the parameter.

+5


source


Here's a simpler example, see if you can solve it:



void f(int);          // takes a non-const int

int main() {
    std::set<int> s;  // elements are const ints
    for (auto n : s) {
        f(n);         // OK!?
    }
}

      

+3


source


std::map<K, V>::value_type

std::pair<const K, V>

as you mentioned. So what is const K

when S*

replaced by K

? The answer that may surprise you is not const S*

. but rather S* const

.

+1


source







All Articles