简体   繁体   中英

Comparators in std::map, std::set and std::priority_queue

All these three containers accept a function object by const reference as opposed to either a value or a forwarding reference. This results in the need for copying the function object into the container's internal storage (at most twice).

Is there a reason for copying a function object twice? As opposed to giving the user the ability to pass any type of function object and have that be constructed into the internal functor storage? That way the library is more general and there are less surprises to the user.


The same philosophy is applied in push_back() functions - they have two overloads, one with a const reference and one with an rvalue reference, because this gives the user more control about whether they want to move the value or copy the value. The library remains efficient in the general case without making any assumptions about the usecase.

I suspect this is a design decision that has been carried over since the pre-C++11 days. Would changing this be a decent proposal for the standard?

Typically, the comparator is a pretty small object that is cheap to copy, and you're only going to construct your container once. That extra one copy one time isn't really going to matter. You're probably not creating a bunch of std::map s in your latency sensitive code. So there's simply not a lot of benefit from introducing more constructors for these containers. And what would such a proposal look like? Would you then want to take the Allocator by rvalue reference as well? Now we're adding a bunch more constructors. Change all the constructors taking a Compare const& to instead take a constrained forwarding references? Now, we broke ABI for still marginal, if any, gain. Constructors are complicated. I'm not even convinced that if std::map were designed today, the interface would look different in this regard. If anything, we'd probably just take Compare by value instead of by const& .

On the other hand, push_back is used a LOT, with a wide variety of types, during the main runtime of programs. Being able to move into a vector , or emplace into a vector , is a huge win. The two situations aren't really comparable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM