Search code examples
c++c++11shared-ptrcomparison-operators

Issue with using shared_ptr with custom equality operator and STL


There seems to be an issue when using shared pointers together with a custom equality operator and an std::list.

I put together the following example code to demonstrate the issue.

Before trying to compile this:

I'm using gcc version 4.5.2 20110127

with the following commandline:

g++ -g -O0 -std=gnu++0x test.cpp

The source won't compile if c++0x features aren't enabled.

#include<list>
#include<boost/shared_ptr.hpp>

using std::list;
using std::shared_ptr;
using std::cout;
using std::endl;

class TestInt
{
   public:
      TestInt(int x);
      bool operator==(const TestInt& other);

   private:
      int _i;
};

TestInt::TestInt(int x)
{
   _i = x;
}

bool
TestInt::operator==(const TestInt& other)
{
   if (_i == other._i){
      return true;
   }
   return false;
}

class Foo
{
   public:
      Foo(TestInt i);
      shared_ptr<TestInt> f(TestInt i);

   private:
      list<shared_ptr<TestInt>> _x;
};

Foo::Foo(TestInt i)
{
   _x.push_back(shared_ptr<TestInt>(new TestInt(i)));
};

shared_ptr<TestInt>
Foo::f(TestInt i)
{
   shared_ptr<TestInt> test(new TestInt(i));
   int num = _x.size();
   list<shared_ptr<TestInt>>::iterator it = _x.begin();
   for (int j=0; j<num; ++j){
      if (test == *it){
         return test;
      }
      ++it;
   }
   throw "Error";
}

int main(){
   TestInt ti(5);
   TestInt ti2(5);
   Foo foo(ti);
   foo.f(ti2);
   std::cout << "Success" << std::endl;
}

I would have expected that the code finishes with Success but instead it throws.

Inserting a * infront of test as well as *it fixes the issue but my understanding is that when the shared_ptr calles __a.get() == __b.get() in its == operator it should use the custom equality operator of TestInt. I don't understand why it is not. Is this a bug?

Thanks in advance.


Solution

  • This is because when you compare two shared_ptr<T>, you are comparing the reference, that is, the memory address that the two instances point to, not the underlying values.