Search code examples
c++c++11operator-overloadingshared-ptrmultiset

Not working: override the default less-than operator of shared_ptr of a class


all. I'm trying to use a std::multiset to have automatic ordering upon insertion. Its elements are std::shared_ptrs to DataCell objects. Here is the code in the header file:

#include <iostream>
#include <string>
#include <set>
#include <memory>

class DataCell
{
public:
    double _cartesianDistance;
};

typedef std::shared_ptr<DataCell> DataCellPtr;

bool operator<(const DataCellPtr &d1, const DataCellPtr &d2)  {
    std::cout << "lalala" << std::endl;
    return d1->_cartesianDistance < d2->_cartesianDistance;
}

typedef std::multiset<DataCellPtr, std::less<DataCellPtr>> DataCellPtrMultiset;

int main(){
    DataCellPtr d1( new DataCell );
    DataCellPtr d2( new DataCell );
    d1->_cartesianDistance = 1.0;
    d2->_cartesianDistance = 2.0;
    DataCellPtrMultiset dms;
    dms.insert( d1 );
    dms.insert( d2 );
}

Expected output:

lalala
lalala

All works fine, except that my custom ordering does not take place, as I was supposed to get "lalala"s printed to my std::out, which is not happening. I imagine the multiset is using the shared_ptr's default ordering. The _cartesianDistance member is a double. Question: how do I override the default shared_ptr ordering?


Solution

  • Instead of using std::less, just supply your own comparator object:

    struct DataCellPtrComparison
    {
      bool operator() (const DataCellPtr &d1, const DataCellPtr &d2) const {
        std::cout << "lalala" << std::endl;
        return d1->_cartesianDistance < d2->_cartesianDistance;
      }
    };
    
    typedef std::multiset<DataCellPtr, DataCellPtrComparison> DataCellPtrMultiset;
    

    "Overriding" the existing operator< for std::shared_ptr in your own namespace is not possible as it is already defined in namespace std and will be found there via ADL before any function with the same signature in a different namespace.