Инициализация multiset с помощью пользовательской функции сравнения в C++

рассмотрим следующую функцию сравнения:

bool compare(std::shared_ptr<myObject> &lhs, std::shared_ptr<myObject> &rhs){
   return lhs->value < rhs->value;
}

Теперь идея состоит в том, чтобы инициализировать multiset типа std::shared_ptr<myObject> который приказывает элементы с вышеуказанной функцией. Поэтому из книги, которую я читал, это должно быть сделано так:

std::multiset<std::shared_ptr<myObject>, decltype(compare)*> myset{compare};

вопрос:

мой вопрос в том, что в объявлении я понимаю, что указатель функции передается для ссылки на функцию сравнения, но почему мы инициализируем набор wtih {compare}?? в чем его важность и почему обязательно так поступать??

4 ответов


потому что набор нужен функтор сравнения для работы. Если вы не укажете его,он будет создан по умолчанию. В этом случае, поскольку вы используете тип function-pointer, построенный по умолчанию, будет нулевым указателем, который нельзя вызвать; поэтому вместо этого вы должны предоставить правильный указатель функции во время выполнения.

лучшим подходом может быть использование типа класса функций (a.к. a. functor type); затем вызов функции может быть разрешен во время компиляции и объект, построенный по умолчанию, будет поступать правильно:

struct compare {
    bool operator()(std::shared_ptr<myObject> &lhs, 
                    std::shared_ptr<myObject> &rhs) const {
        return lhs->value < rhs->value;
    }
};

std::multiset<std::shared_ptr<myObject>, compare> myset;

компаратор, переданный шаблону, должен быть типом чего-то, что можно вызвать с помощью оператора вызова функции. Это будет либо класс, который перегрузил этот оператор, либо тип лямбды или указателя функции. В cunstrutor set должен быть передан экземпляр этого типа. Так что decltype(compare)* - тип указателя функции и &compare - это указатель на функцию.


decltype(compare)* в параметре template указывает тип компаратора. Он не говорит , который функция должна использоваться-является ли это compare, foo, bar или что-то еще. Следовательно, параметр конструктора.


чтобы получить доступ к вашим элементам, вам нужно предоставить функцию для строгий слабый заказ для вашего типа.

std::multiset есть следующий конструктор:

 explicit multiset (const key_compare& comp = key_compare(),
               const allocator_type& alloc = allocator_type());

как вы можете видеть, вы можете сделать это путем передачи comp указатель функции (или объект функции) на конструктор.