Search code examples
c++language-designc++23

Why does heterogenous version of erase for associative containers take in forwarding reference?


Is there any particular reason why heterogeneous version of erase in associative containers (std::map, std::unordered_map, std::multimap and std::unordered_multimap) takes in a forwarding reference and all other heterogeneous functions (find/equal_range, count, contains) take in const-reference?

For instance in case of std::unordered_map:

template<class K> iterator find(const K& k);
template<class K> const_iterator find(const K& k) const;
template<class K> size_type erase(K&& x);

https://en.cppreference.com/w/cpp/container/unordered_map/erase (overload 4) https://en.cppreference.com/w/cpp/container/unordered_map/find (overloads 3/4)

Section 24.5.4.1 of (lastest working draft) n4910

(This, as mentioned, applies to other containers as well.)


Solution

  • After doing a bit more research I've found the original proposal p2077 which explains it (paragraphs 2 and 3.1).

    If the overload

    template <class K>
    size_type erase( const K& x );
    

    existed, it would be chosen when passing an object of a type, which is implicitly convertible to either iterator or const_iterator and that is not what users might expect.

    Additionally it is not possible to create a valid constraints for the mentioned overload because the value category of K is lost due to template argument deduction from const K& function parameter. Therefore, we cannot define constraints over K for the arbitrary case. To propagate the information about the value category of K we define the function parameter for heterogeneous erasure as forwarding reference.

    A more detailed explanation can be found in proposal.