I'm trying to create "rollback" functionality for a small database assignment. I have a stack of binary search trees that I am using to store backups of the database called:
GenStack<GenBST<Student>> masterStudentStack;
Both the stack and BST are my own implementations (per the instructions for my assignment).
I have no problem pushing a copy of the BST onto the stack,
masterStudentStack.push(*masterStudent);
however when I try to retrieve this BST and return it to my primary BST pointer using:
void rollBack() {
masterStudent = new GenBST<Student>(masterStudentStack.pop());
}
I receive an error.
Menu.cpp:419:63: error: invalid initialization of non-const reference of
type ‘GenBST<Student>&’ from an rvalue of type ‘GenBST<Student>’
masterStudent = new GenBST<Student>(masterStudentStack.pop());
~~~~~~~~~~~~~~~~~~~~~~^~
In file included from Menu.h:7:0,
from Menu.cpp:1:
GenBST.h:49:1: note: initializing argument 1 of
‘GenBST<T>::GenBST(GenBST<T>&) [with T = Student]’
GenBST<T>::GenBST(GenBST<T>& other) {
^~~~~~~~~
The copy constructor for the BST is functional when an lvalue is passed in by reference, (this is the declaration for the constructor)
GenBST(GenBST<T>& other);
but I don't know how to pop something off the stack in a way in which the copy constructor will accept it. So, my question is: Can I something create a new BST using the rvalue "stack.pop()"?
Thanks, Matthew
Edit:
After adding "const" to my BST copy constructor, I got this error
In file included from Menu.h:7:0,
from Menu.cpp:1:
GenBST.h: In instantiation of ‘GenBST<T>::GenBST(const GenBST<T>&) [with T =
Student]’:
Menu.cpp:419:65: required from here
GenBST.h:50:22: error: passing ‘const GenBST<Student>’ as ‘this’ argument
discards qualifiers [-fpermissive]
if(other.getRoot() == NULL) {
GenBST.h:77:17: note: in call to ‘GenTreeNode<T>* GenBST<T>::getRoot()
[with T = Student]’
GenTreeNode<T>* GenBST<T>::getRoot()
^~~~~~~~~
GenBST.h:54:32: error: binding ‘GenTreeNode<Student>* const’ to reference of
type ‘GenTreeNode<Student>*&’ discards qualifiers
copyTree(this->root, other.root);
~~~~~~^~~~
GenBST.h:108:6: note: initializing argument 2 of ‘void
GenBST<T>::copyTree(GenTreeNode<T>*&, GenTreeNode<T>*&) [with T = Student]’
void GenBST<T>::copyTree(GenTreeNode<T> *& thisNode, GenTreeNode<T> *&
otherNode) {
Here is my constructor and the method it calls:
template <class T>
GenBST<T>::GenBST(const GenBST<T>& other) {
if(other.getRoot() == NULL) {
root = NULL;
}
else {
copyTree(this->root, other.root);
}
}
template <class T>
void GenBST<T>::copyTree(GenTreeNode<T> *& thisNode, GenTreeNode<T> *&
otherNode) {
if(otherNode == NULL) {
thisNode = NULL;
}
else {
thisNode = new GenTreeNode<T>(otherNode->key);
copyTree(thisNode->left, otherNode->left);
copyTree(thisNode->right, otherNode->right);
}
}
Any ideas?
Edit 2:
Thank so much for the help everybody. I added const to both my getRoot() and copyTree() methods and am now down to one error.
GenBST.h: In instantiation of ‘GenBST<T>::GenBST(const GenBST<T>&) [with T =
Student]’:
Menu.cpp:419:65: required from here
GenBST.h:54:32: error: binding ‘GenTreeNode<Student>* const’ to reference of
type ‘GenTreeNode<Student>*&’ discards qualifiers
copyTree(this->root, other.root);
~~~~~~^~~~
GenBST.h:108:6: note: initializing argument 2 of ‘void
GenBST<T>::copyTree(GenTreeNode<T>*&, GenTreeNode<T>*&) const [with T =
Student]’
void GenBST<T>::copyTree(GenTreeNode<T> *& thisNode, GenTreeNode<T> *&
otherNode) const {
The canonical form of a copy constructor takes a reference to a const object to copy. Conceptually, making a copy of something normally implies that the original object remains unchanged. There should hardly ever be a need to modify the object you're copying. An rvalue can be bound to a reference to const but not to a reference to non-const. Unless making a copy of a GenBST
really does actually entail modifying the object you're copying (I assume and sincerely hope it does not), you can simply change the signature of your copy constructor to
GenBST(const GenBST& other);