5

I'm creating my own custom Filter class for use in boost::filtered_graph. The WeightMap concept must have a default constructor, copy constructor, and assignment operator.

I've created the class below, which has a std::shared_ptr private member. My question is how I'm supposed to write the assignment operator. The copy constructor wasn't a problem, but the assignment operator doesn't work.

class BFDMFilter
{
private:
const BGraph* m_battlemap;
const std::shared_ptr<MoveAbility> m_mv_ab;

public:
BFDMFilter() : m_battlemap(nullptr), m_mv_ab() { }
BFDMFilter(const BGraph* bmap, std::shared_ptr<MoveAbility> mv) : m_battlemap(bmap), m_mv_ab(mv) { }

BFDMFilter(const BFDMFilter& filter) : m_battlemap(filter.m_battlemap), m_mv_ab(filter.m_mv_ab) { }
BFDMFilter& operator=(const BFDMFilter& filter) 
{
  if(this != &filter)
  {
m_battlemap = filter.m_battlemap;
m_mv_ab = filter.m_mv_ab;
  }

  return *this;
}

bool operator()(const Edge& edge) const 
{ 
  Tile::TileEdge path = (*m_battlemap)[edge];

  return m_mv_ab->CanMove(path.TerrainType()) > 0.0;
}

bool operator()(const Vertex& vertex) const 
{ 
  Tile tile = (*m_battlemap)[vertex];

  return m_mv_ab->CanMove(tile.TerrainType()) > 0.0;
}
};

Which then gives me a compile error:

error: passing ‘const std::shared_ptr<momme::battle::MoveAbility>’ as ‘this’ argument of ‘std::shared_ptr<_Tp>& std::shared_ptr<_Tp>::operator=(std::shared_ptr<_Tp>&&) [with _Tp = momme::battle::MoveAbility, std::shared_ptr<_Tp> = std::shared_ptr<momme::battle::MoveAbility>]’ discards qualifiers [-fpermissive]

I understand why; the assignment operator modifies the reference count of the shared_ptr when it does the assignment, so that it can keep track of how many open references there are. But then, how do I write the assignment operator? std::weak_ptr has the same behavior, and if I make the reference non-const, then the boost library complains that the function is deleted.

2
  • 2
    I'm not sure why you need the pointer to be const...do you mean std::shared_ptr<const MoveAbility> m_mv_ab instead? Do you want the std::shared_ptr itself const or the object it's pointing at to be const? Commented Mar 3, 2013 at 22:58
  • 1
    You can't do assignment with any const data member. This isn't specific to shared_ptr. Commented Mar 3, 2013 at 23:01

1 Answer 1

12

There doesn't seem to be any reason from your code to declare m_mv_ab as

const std::shared_ptr<MoveAbility> m_mv_ab;

which is the smart-pointer version of:

MoveAbility * const m_mv_ab;

(constant pointer to non-constant MoveAbility)

If you don't want to modify the pointed-to MoveAbility object and want it to be const, you should do:

std::shared_ptr<const MoveAbility> m_mv_ab;

which is the smart-pointer version of:

const MoveAbility * m_mv_ab;

(non-constant pointer to constant MoveAbility)

To make this a bit more intuitive you can use const as a suffix always and always read right-to-left, except that std::shared_ptr<X> is read "(smart) pointer to X":

std::shared_ptr<MoveAbility> const m_mv_ab; // const ptr to non-const MoveAbility
MoveAbility * const m_mv_ab; // const ptr to non-const MoveAbility

std::shared_ptr<MoveAbility const> m_mv_ab; // non-const ptr to const MoveAbility
MoveAbility const * m_mv_ab; // non-const ptr to const MoveAbility

but most people use const as a prefix whenever possible, which makes it confusing.

Sign up to request clarification or add additional context in comments.

2 Comments

What a dumb mistake; I can't believe I missed that. Thanks for pointing it out.
@Brad happens all the time, it's not that intuitive

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.