简体   繁体   中英

C++ shared_ptr equality operator

The equality operator for shared_ptr's is defined as follows:

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

This seems broken. Would it not have been better to forward the equality to what a and b are pointing to? Or would that be an unfair restriction on users of the library (in that they have to provide an equality operator)?

If I have a map or a hash_table containing shared_ptrs, then the current definition makes equality unusable. For example, consider

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

Won't we want to check that the ptrs for each int in m1 and m2 are pointing to the same value?

I can implement my own equality by flattening m1, m2 out (constructing sets from each, dereferencing shared_ptrs along the way). Is there an STL trick that will accomplish this or some other way to test equality in the presence of shared_ptrs neatly?

It's not broken, because a shared_ptr is conceptually a pointer, therefore it implements pointer-wise equality. When you test two pointers for equality, you want to know whether they point to the same place in memory.

I think the idea is that comparing two shared_ptr instances is about as useful as comparing two pointers. If you want a std::map containing shared_ptr s or plain old pointers to objects, you'll have to override the predicate with something that compares the pointed-to objects in either case.

In the case of comparing two maps, you would probably want to use the version of std::equal that takes a predicate.

Just ran into a problem where I could use both types of equivalence. An unordered set of shared_ptr where I wanted the equivalence to be based on the contents of the pointed to objects. This can be implemented using a template specialization of hash and an overloaded ==. Now I have another container that also contains these pointers (an edge incidence list of sorts), but since we already know they are unique because we used the set, we can rely on pointer equivalence. Although the original equivalence would also work, it might be more efficient to just rely on the pointer equivalence in the second case -- this depends on the amount of data that are in the instances being compared.

So, to answer the question. No it would not have been better, because how you use the flexibility provided depends on the problem being solved.

you can write your own subclass of std::shared_ptr with a operator== that does what you want. then the map can contain this objects

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

because the operator== isn't virtual, this will not work with pointers to shared_ptr 's

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM