Copy assign a map if element is not assignable

In addition to @MofX's answer I'd like to add some resources here, also because the quoted text contains invalid links.

From [unord.map]/2 (emphasis mine):

An unordered_­map satisfies all of the requirements of a container, of an unordered associative container, and of an allocator-aware container.

This leads to [container.requirements.general]/16, where for the assignment expression in Table 86 the requirements are (emphasis mine):

Requires: T is CopyInsertable into X and CopyAssignable.

Of course, the type used in the OP's example struct const_int { const int x = 1; }; is not copy assignable (due to the const and no user-defined assignment operator) and therefore the compilation fails.

I hope this makes it clearer.

(Disclaimer: Initially I was convinced MSVC has a bug here but I was proven wrong)


Quoting Billy Robert O'Neil III from visual studio developer community this is not a bug:

This is not a bug. unordered_map is an allocator-aware container, and the assignment operation of allocator-aware containers requires that the value_type be copy assignable - see containers.allocatoraware - and then unord.req says that for the purposes of requirements in the unordered containers, one looks to key_type and mapped_type instead.

This happened to work in previous releases of Visual C++ because std::list, out of which std::unordered_map is constructed, used to deallocate all nodes during an assignment operation, so even though it was permitted to assign elements, we happened not to. But that meant that assigning 100 values into a list already containing 100 elements would do 200 unnecessary calls to the allocator: deallocating all 100 old nodes, then allocating 100 new nodes. The behavior change you observe is because in VS2019 Update 2, we implemented an optimization to reuse already-allocated nodes in an assignment.

Tags:

C++