I have a std::map
with shared_ptr<T>
keys, and I need it to use the actual value (of type T
, i.e. *key
) for lookups, not the value of the shared pointer itself.
I know I can write my own custom comparator (as I've done below), but I was wondering if the STL supplies a comparator specifically for this purpose.
To demonstrate what I'm talking about, I created this simple example that uses a std::set
of strings (I've also put it on GitHub as a gist):
#include <set>
#include <string>
#include <memory>
#include <iostream>
#include <functional>
template< typename T >
struct shared_ptr_comparator {
bool operator()(const std::shared_ptr<T> &a, const std::shared_ptr<T> &b) const {
return std::less<T>()(*a, *b);
}
};
void ptr_set_with_custom_comparator() {
std::set< std::shared_ptr<std::string>, shared_ptr_comparator<std::string> > ptr_set;
ptr_set.insert(std::make_shared<std::string>("world"));
ptr_set.insert(std::make_shared<std::string>("hello"));
ptr_set.insert(std::make_shared<std::string>("abc"));
for(auto const& entry : ptr_set) {
std::cout << *entry << std::endl;
}
}
void ptr_set_with_owner_less() {
std::set< std::shared_ptr<std::string>, std::owner_less<std::shared_ptr<std::string>> > ptr_set;
ptr_set.insert(std::make_shared<std::string>("world"));
ptr_set.insert(std::make_shared<std::string>("hello"));
ptr_set.insert(std::make_shared<std::string>("abc"));
for(auto const& entry : ptr_set) {
std::cout << *entry << std::endl;
}
}
void raw_set() {
std::set<std::string> raw_set;
raw_set.insert("world");
raw_set.insert("hello");
raw_set.insert("abc");
for(auto const& entry : raw_set) {
std::cout << entry << std::endl;
}
}
int main() {
std::cout << "A basic set of strings:" << std::endl;
raw_set();
std::cout << std::endl;
std::cout << "A set of shared_ptr<string>s with owner_less as the comparator:" << std::endl;
ptr_set_with_owner_less();
std::cout << std::endl;
std::cout << "A set of shared_ptr<string>s with the comparator shared_ptr_comparator:" << std::endl;
ptr_set_with_custom_comparator();
return 0;
}
The code above can be complied with clang++ -Wall -std=c++11
. Here's the output:
A basic set of strings:
abc
hello
world
A set of shared_ptr<string>s with owner_less as the comparator:
world
hello
abc
A set of shared_ptr<string>s with the comparator shared_ptr_comparator:
abc
hello
world
A sorted ordering when iterating and printing the contents std::set
implies that the _actual underlying values) are being compared.
The function raw_set
doesn't use shared_ptr
, and just uses set<string>
, and is simply present for reference.
The function ptr_set_with_custom_comparator
works as expected. I am able to achieve what I want with my own shared_ptr_comparator
.
However, the output of ptr_set_with_owner_less
has left me puzzled. Is owner_less
(or owner_before
) utilizing the values of the pointers themselves?
Based on all of this, I have two questions:
-
Does anything equivalent to
shared_ptr_comparator
(defined in the program above), exist in the STL? I ask because the comparator I wrote seems like a really common use case, and I would be very surprised if the STL didn't have anything equivalent to it. -
What exactly does owner_less and owner_before (which it calls) do? Do they simply check for equivalence of the underlying pointers? I'm not sure if I'm using it right.
Thanks in advance for any answers to this question.
Aucun commentaire:
Enregistrer un commentaire