I want std::set
if shared_ptr's
to compare the pointee's, not pointers.
I have this example:
std::shared_ptr<std::string> s(new std::string("abc"));
std::shared_ptr<std::string> p(new std::string("abc"));
std::set<std::shared_ptr<std::string>> S;
S.insert(s);
S.insert(p);
std::cout << S.size();
As you can see I am putting the same element in the set
but this outputs 2.
How can I make set's insert to use the comparison criteria of underlying strings? And what if its not a string but more complex object?
The second template parameter of std::set
is the type of the comparator to be used (default is std::less<Key>
):
#include <iostream>
#include <memory>
#include <set>
#include <string>
struct deref_less {
bool operator()(const auto& a, const auto& b) const { return (*a) < (*b); }
using is_transparent = void;
};
int main() {
std::shared_ptr<std::string> s(new std::string("abc"));
std::shared_ptr<std::string> p(new std::string("abc"));
std::set<std::shared_ptr<std::string>, deref_less> S;
S.insert(s);
S.insert(p);
std::cout << S.size();
}
1
auto
parameters for convenience with C++20, before the comparator is a bit more verbose. using is_transparent = void;
to enable eg the set::find
overload that accepts a std::unique_ptr<std::string>
(see godbolt example).