Vasiliy Galkin Vasiliy Galkin - 1 year ago 61
C++ Question

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

According to

std::map
documentation, it stores the key-value pairs in
std::pair<const Key, Value>
, so the keys in the map are const.

Now imagine that I have an
std::map
where the keys are the pointers to some objects.

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


Let's also assume there is a function
foo
that accepts
S*
parameter.

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


Now, the question is: when I iterate over
MyMap
with range-based for-loop, I am able to pass the map element key 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, even though my
static_assert
succeeds (so I assume that the type of
elem.first
is
const S*
), the call to
foo
compiles fine, and therefore it look as if I'm able to modify the object behind pointer-to-const.

Why am I able to do that?

P.S. Here's a live example at Coliru that illustrates my point. For brevity, I use
int
instead of
S
and
Data
.

Answer Source

so I assume that the type of elem.first is const S*

No. The key stored in map is const, that means for std::map<S*, Data>, the key will be S* const (i.e. const pointer), not const S* (i.e. pointer to const). So it's fine to pass it to foo(S* ptr), the const pointer itself will be copied to the parameter.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download