According to cppreference.com, std::shared_ptr
provides a full set of relative operators (==, !=, <, ...), but the semantics of comparison aren\'t specified. I a
The first thing, as others have already pointed out is that inheritance is not the way to go. But rather than the convoluted wrapper suggested by the accepted answer, I would do something much simpler: Implement your own comparator for your own types:
namespace myns {
struct mytype {
int value;
};
bool operator<( mytype const& lhs, mytype const& rhs ) {
return lhs.value < rhs.value;
}
bool operator<( std::shared_ptr const & lhs, std::shared_ptr const & rhs )
{
// Handle the possibility that the pointers might be NULL!!!
// ... then ...
return *lhs < *rhs;
}
}
The magic, which is not really magic at all is Argument Dependent Lookup (aka. Koening Lookup or ADL). When the compiler encounters a function call it will add the namespace of the arguments to lookup. If the objects are the instantiation of a template, then the compiler will also add the namespaces of the types used to instantiate the template. So in:
int main() {
std::shared_ptr a, b;
if ( a < b ) { // [1]
std::cout << "less\n";
} else {
std::cout << "more\n";
}
}
In [1], and because a
and b
are objects user defined types (*) ADL will kick in and it will add both std
and myns
to the lookup set. It will then find the standard definition of operator<
for std::shared_ptr
that is:
template
bool std::operator<(shared_ptr const& a, shared_ptr const& b) noexcept;
And it will also add myns
and add:
bool myns::operator<( mytype const& lhs, mytype const& rhs );
Then, after lookup finishes, overload resolution kicks in, and it will determine that myns::operator<
is a better match than std::operator<
for the call, as it is a perfect match and in that case non-templates take preference. It will then call your own operator<
instead of the standard one.
This becomes a bit more convoluted if your type is actually a template, if it is, drop a comment and I will extend the answer.
(*) This is a slight simplification. Because operator<
can be implemented both as a member function or a free function, the compiler will check inside std::shared_ptr<>
for member operator<
(not present in the standard) and friends. It will also look inside mytype
for friend
functions... and so on. But at the end it will find the right one.