Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

c++ compiler choosing selectively when it throws errors

The code below is just a binary tree that inserts Nodes into it.

When I run the code below, it throws the error (in insert method of Tree) of

"Line 135: Char 35: error: assigning to ‘Node *’ from
‘const Node *’ discards qualifiers on.left = &add"

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

, I’m told this occurred because I’m trying to assign a constant to a non constant, which is supposedly never allowed.

But for some reason, in the constructor for Tree, I also assign the constant reference to a non constant member variable Root using member initialization list, but here the error is not thrown.

I’m confused by this inconsistency. My textbook & cpp reference page on constant qualifier doesn’t address why the member initialization list allows me to assign constants to non constants. Why am I allowed to assign constant variable to non constant variables, but other times can’t? In which situations am I allowed to assign constants to non constants?

#include <sstream>
#include <string>
#include <vector>
#include <iostream>

using namespace std;

template <typename T>
struct Node {
    T val;
    Node* left;
    Node* right;

    Node (const T &val) : val(val), left(nullptr), right(nullptr) {

    }

};


template <typename T>
class Tree {
    public:
        Node<T> root;
        Tree(const Node<T>& r) : root(r) { //why no error here? I'm also discarding qualifier!
            std::cout<< "why no error?"<<std::endl;
        }



        void insert(const Node<T> &add) {
            Node<T>& on = root;
            
            while (true) {
                if (add.val < on.val) {
                    if (on.left == nullptr) {
                        on.left = &add; //why error here????!!!!
                        return ;
                    } else {
                        on=on->left;
                    }
                } else {
                    if (on.right == nullptr) {
                        on.right=&add;
                        return ;
                    } else {
                        on=on->right;
                    }
                }
            }
            
            return ;
        }


}; 




int main() {
    using namespace std;

    Tree<int> mytree(Node<int>(15));
    
    mytree.insert(Node<int>(2));
    
    cout<<"code finished without undefined behavior"<<endl;

    return 0;
}

>Solution :

The rule about not assigning const to non-const exists because doing so would allow you to modify const objects. E.g.

const int one = 1;
const int* ptr = &one;
int* bad = ptr;   // not really allowed
*bad = 2;         // changes the const object `one`

But the other situation you describe is different

template <typename T>
class Tree {
public:
    Node<T> root;
    Tree(const Node<T>& r) : root(r) {}
    ...
};

Here r is a const reference to an object which is being used to initialise a completely different object called root. If you subsequently change root it has no effect at all on the object referred to by r. So there is no problem with const here.

But one small change and there is an error

template <typename T>
class Tree {
public:
    Node<T>& root; // a reference
    Tree(const Node<T>& r) : root(r) {}
    ...
};

Now root is a reference, not a separate object, so the const to non-const rule applies.

In general you need to understand the difference between copying objects and copying references or pointers to objects. When you copy an object there are now two separate independent objects, when you copy a pointer or a reference there is only one actual object.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading