4

I got troubles undertanding the following error:

Error 1 error C2440: '=' : cannot convert from 'const X<...> *const ' to 'X<...> *const '

I am trying to use a pointer to const pointer to keep track of a Node during a tree traversal:

bool IsValid() const
  {
    X* const* previousNode = new X*;
    return this->IsValid(previousNode);
  }

  bool IsValid(X* const* previousNode) const
  {
    ...
    if (!*previousNode)
      *previousNode = this; // Error
    ...

    return true;
  }

Why is this is a const X* const type and cannot be used as a *Const * ?

As the method is a const method, my understanding is that it protects the object itself of being modified. Then why does the compiler try to enforce the constness of a pointer to pointer returning this?

I have not been able to find an answer to this question using the search engine of stack overflow.

Thank you for your answers.

Here is the finale code I finally used if I can be a use for someone:

bool IsValid() const
  {
    std::unique_ptr<const BST*> previousNode = std::unique_ptr<const BST*>(new const BST*);
    *previousNode = nullptr;
    return this->IsValid(prevNode);
  }

bool IsValid(std::unique_ptr<const BST*>& previousNode) const
{
  // Recurse on left child without breaking if not failing
  if (this->leftChild &&!this->leftChild->IsValid(previousNode))
    return false;

  // First node retrieved - assign
  if (!*previousNode)
    *previousNode = this;
  // Previous data does not compare well to the current one - BST not valid
  else if (!Compare()((*previousNode)->data, this->data))
    return false;

  // Set current node
  *previousNode = this;

  // Recurse on right child
  if (this->rightChild && !this->rightChild->IsValid(previousNode))
    return false;

  return true;
}

Just playing with template and simple data structure. Thank you for your answers.

  • 2
    You pass an uninitialized pointer to `IsValid` – M.M Jul 04 '16 at 20:26
  • Thx, tried to focus on the error - corrected version: bool IsValid() const { const BST** previousNode = new const BST*; *previousNode = nullptr; return this->IsValid(previousNode); } bool IsValid(const BST** previousNode) const – Jeulin-L Michael Jul 04 '16 at 20:41

2 Answers2

4

Let's start simple:

  • a const X* is a pointer to a constant X
  • a const X* const is a constant pointer to a constant X
  • a const X* const*is a pointer to a constant pointer to a constant

Back to your problem:

  • X* const* previousNode is a pointer to a constant pointer to an X
  • so *previousNode is a constant pointer to an X
  • but *previousNode = ... tries to assign something to this constant pointer. It's not possible, the pointer is constant !
Christophe
  • 68,716
  • 7
  • 72
  • 138
  • To my previous understanding *previousNode = ... means: My non-const pointer value is a const object I assign my non-const pointer value to a new const object But it seems that * const * is a non-const pointer on a const value and this pointer cannot be modified. Then when the * const * syntax would make sens? – Jeulin-L Michael Jul 04 '16 at 20:52
  • 1
    The thing is that there are 2 * so there is here a double indirection. You have declared previousNode to be a non const pointer to a const pointer. This could make sense for example if you want to protect the pointer you're pointing to (see [online demo](http://ideone.com/NKVs0Z)). This could make sense for example if there's a risk that previousNode points to a pointer that is member of X (because isValid() is itself const and you must ensure this promise, i.e. that the member function will not accidentally modify the state of the state of the object. – Christophe Jul 04 '16 at 21:19
3

The signature of the IsValid method specifies (by using const), that this is a constant object, i.e. its type is const X*. Changing the type of previousNode to const X** should solve your problem.

majk
  • 827
  • 5
  • 12