Оператор равенства C shared_ptr

#c #map #shared-ptr #equality

#c #словарь #общий-ptr #равенство

Вопрос:

Оператор равенства для shared_ptr определяется следующим образом:

 template<class T, class U> inline bool operator==(
    shared_ptr<T> const amp; a, shared_ptr<U> const amp; b)
{
    return a.get() == b.get();
}
  

Это кажется сломанным. Не было бы лучше перенаправить равенство на то, что a и b
указывают на? Или это было бы несправедливым ограничением для пользователей библиотеки (в том
они должны предоставлять оператор равенства)?

Если у меня есть map или hash_table, содержащие shared_ptrs, то текущее определение делает равенство непригодным для использования. Например, рассмотрим

 std::map<int, std::tr1::shared_ptr<T> > m1, m2;
  

Не захотим ли мы проверить, что ptr для каждого int в m1 и m2 указывают на одно и то же значение?

Я могу реализовать свое собственное равенство, сглаживая m1, m2 (создавая наборы из каждого, попутно разыменовывая shared_ptrs). Существует ли уловка STL, которая позволит выполнить это или какой-либо другой способ аккуратно проверить равенство при наличии shared_ptr ?

Комментарии:

1. Это зависит от того, что вы подразумеваете под равенством. Для обычных указателей это означает «указывать на один и тот же объект». Мне кажется разумным распространить эту концепцию равенства на shared_pointer.

Ответ №1:

Это не нарушено, потому что shared_ptr концептуально является указателем, следовательно, он реализует равенство по указателю. Когда вы проверяете два указателя на равенство, вы хотите знать, указывают ли они на одно и то же место в памяти.

Ответ №2:

Я думаю, идея в том, что сравнение двух shared_ptr экземпляров примерно так же полезно, как сравнение двух указателей. Если вы хотите, std::map содержащий shared_ptr s или простые старые указатели на объекты, вам придется переопределить предикат чем-то, что сравнивает указанные объекты в любом случае.

В случае сравнения двух отображений вы, вероятно, захотите использовать версию std::equal , которая принимает предикат.

Ответ №3:

Только что столкнулся с проблемой, когда я мог использовать оба типа эквивалентности. Неупорядоченный набор shared_ptr, где я хотел, чтобы эквивалентность основывалась на содержимом объектов, на которые указывают. Это может быть реализовано с использованием шаблонной специализации хэша и перегруженного == . Теперь у меня есть другой контейнер, который также содержит эти указатели (своего рода список встречаемости ребер), но поскольку мы уже знаем, что они уникальны, поскольку мы использовали set, мы можем полагаться на эквивалентность указателей. Хотя исходная эквивалентность также будет работать, возможно, было бы более эффективно просто полагаться на эквивалентность указателя во втором случае — это зависит от объема данных, которые находятся в сравниваемых экземплярах.

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

Ответ №4:

вы можете написать свой собственный подкласс std::shared_ptr с operator== , который делает то, что вы хотите. тогда карта может содержать эти объекты

 template<class t>
class my_shared_ptr : public std::shared_ptr<t>
{
    bool operator==(const std::shared_ptr<t> amp;other)
    {
        return (*this->get()) == (*other.get());
    }
}
  

поскольку operator== не является виртуальным, это не будет работать с указателями на shared_ptr ‘s