Reputation: 1
I implemented the following a Binary Search Tree using a template class:
#ifndef ROSTER_
#define ROSTER_
#include "BinaryNode.hpp"
#include "Visitor.hpp"
#include "Student.hpp"
#include "Printer.hpp"
#include <vector>
#include <memory>
template<class T>
class Roster
{
public:
Roster(); // Constructor
Roster(const Roster<T>& tree); //Copy constructor
~Roster(); // Destructor
bool isEmpty() const;
int getHeight() const;
int getNumberOfNodes() const;
void add(const T& new_item);
void add(const std::vector<T>& new_items);
void remove(const T& target);
void display();
T find(const T& item);
void clear();
void inorderTraverse(Visitor<T>& visit) const;
Roster& operator= (const Roster<T>& rhs);
private:
std::shared_ptr<BinaryNode<T>> root_ptr_;
std::shared_ptr<BinaryNode<T>> copyTree(const std::shared_ptr<BinaryNode<T>> old_tree_root_ptr) const;
void destroyTree(std::shared_ptr<BinaryNode<T>> sub_tree_ptr);
int getHeightHelper(std::shared_ptr<BinaryNode<T>> sub_tree_ptr) const;
auto placeNode(std::shared_ptr<BinaryNode<T>> sub_tree_ptr, std::shared_ptr<BinaryNode<T>> new_node_ptr);
auto removeValue(std::shared_ptr<BinaryNode<T>> sub_tree_ptr, const T target);
auto removeNode(std::shared_ptr<BinaryNode<T>> node_ptr);
auto removeLeftmostNode(std::shared_ptr<BinaryNode<T>> nodePtr, T& inorderSuccessor);
void inorder(Visitor<T>& visit, std::shared_ptr<BinaryNode<T>> tree_ptr) const;
//Operator overloading for students objects
friend bool operator <(const Student& a, const Student& b);
friend bool operator >(const Student& a, const Student& b);
friend bool operator ==(const Student& a, const Student& b);
};
#include "Roster.cpp"
#endif
In this case I want to implement the same class but only using object of type Student. The implementation works when declaring as Roster<Student> my_student;
However when I try implementing the same code but instead of a template class is a class that only takes objects of type student therefore removing the template and specifying each function the data type for the BinaryNode<> I get an error time on two specific functions:
auto removeNode(std::shared_ptr<BinaryNode<Student>> node_ptr);
auto removeLeftmostNode(std::shared_ptr<BinaryNode<Student>> nodePtr, Student& inorderSuccessor);
I get an "declaration is incompatible with "" Message:
auto Roster::removeNode(std::shared_ptr<BinaryNode<Student>> node_ptr)
{
}
To see the full implementation of the .cpp for Roster.hpp for template class:
#include "Roster.hpp"
//Constructor
template<class T>
Roster<T>::Roster()
{
root_ptr_ = nullptr;
}
//Copy Constructor
template<class T>
Roster<T>::Roster(const Roster& tree)
{
root_ptr_ = copyTree(tree.root_ptr_);
}
//Destructor
template<class T>
Roster<T>::~Roster()
{
destroyTree(root_ptr_);
}
//Check if empty
template<class T>
bool Roster<T>::isEmpty() const
{
return root_ptr_ == nullptr;
}
//Clear
template<class T>
void Roster<T>::clear()
{
destroyTree(root_ptr_);
}
//Get height
template<class T>
int Roster<T>::getHeight() const
{
return getHeightHelper(root_ptr_);
}
//Add
template<class T>
void Roster<T>::add(const T& new_item)
{
auto new_node_ptr = std::make_shared<BinaryNode<T>>(new_item);
root_ptr_ = placeNode(root_ptr_, new_node_ptr);
}
//Add with vector
template<class T>
void Roster<T>::add(const std::vector<T>& new_items)
{
for(int i = 0; i < new_items.size(); i++)
{
auto new_node_ptr = std::make_shared<BinaryNode<T>>(new_items[i]);
root_ptr_ = placeNode(root_ptr_, new_node_ptr);
}
}
//Remove
template<class T>
void Roster<T>::remove(const T& target)
{
root_ptr_ = removeValue(root_ptr_, target);
}
//Diplay
template<class T>
void Roster<T>::display()
{
Printer p;
inorderTraverse(p);
}
template<class T>
void Roster<T>::inorderTraverse(Visitor<T>& visit) const
{
inorder(visit, root_ptr_);
}
//Helper function
template<class T>
std::shared_ptr<BinaryNode<T>> Roster<T>::copyTree(const std::shared_ptr<BinaryNode<T>> old_tree_root_ptr) const
{
std::shared_ptr<BinaryNode<T>> new_tree_ptr;
// Copy tree nodes during preorder tranversal
if(old_tree_root_ptr != nullptr)
{
new_tree_ptr = std::make_shared<BinaryNode<T>>(old_tree_root_ptr->getItem(), nullptr, nullptr);
new_tree_ptr->setLeftChildPtr(copyTree(old_tree_root_ptr->getLeftChildPtr()));
new_tree_ptr->setRightChildPtr(copyTree(old_tree_root_ptr->getRightChildPtr()));
}
return new_tree_ptr;
}
template<class T>
void Roster<T>::destroyTree(std::shared_ptr<BinaryNode<T>> sub_tree_ptr)
{
if(sub_tree_ptr != nullptr)
{
destroyTree(sub_tree_ptr->getLeftChildPtr());
destroyTree(sub_tree_ptr->getRightChildPtr());
sub_tree_ptr.reset();
}
}
template<class T>
int Roster<T>::getHeightHelper(std::shared_ptr<BinaryNode<T>> sub_tree_ptr) const
{
if(sub_tree_ptr == nullptr)
{
return 0;
}
else
{
return 1 + std::max(getHeightHelper(sub_tree_ptr->getLeftChildPtr()), getHeightHelper(sub_tree_ptr->getRightChildPtr()));
}
}
template<class T>
auto Roster<T>::placeNode(std::shared_ptr<BinaryNode<T>> sub_tree_ptr, std::shared_ptr<BinaryNode<T>> new_node_ptr)
{
if(sub_tree_ptr == nullptr)
{
return new_node_ptr;
}
else
{
if(sub_tree_ptr->getItem() > new_node_ptr->getItem())
{
sub_tree_ptr->setLeftChildPtr(placeNode(sub_tree_ptr->getLeftChildPtr(), new_node_ptr));
}
else
{
sub_tree_ptr->setRightChildPtr(placeNode(sub_tree_ptr->getRightChildPtr(), new_node_ptr));
}
return sub_tree_ptr;
}
}
template<class T>
auto Roster<T>::removeValue(std::shared_ptr<BinaryNode<T>> sub_tree_ptr, const T target)
{
if(sub_tree_ptr == nullptr)
{
return sub_tree_ptr;
}
if(sub_tree_ptr->getItem() == target)
{
sub_tree_ptr = removeNode(sub_tree_ptr);
return sub_tree_ptr;
}
else
{
if(sub_tree_ptr->getItem() > target)
{
sub_tree_ptr->setLeftChildPtr(removeValue(sub_tree_ptr->getLeftChildPtr(), target));
}
else
{
sub_tree_ptr->setRightChildPtr(removeValue(sub_tree_ptr->getRightChildPtr(), target));
}
return sub_tree_ptr;
}
}
template<class T>
auto Roster<T>::removeNode(std::shared_ptr<BinaryNode<T>> node_ptr)
{
//Case 1: Node is a leaf - it is deleted
if(node_ptr->isLeaf())
{
node_ptr.reset();
return node_ptr;
}
//Case 2: Node has one child - parent adopts child
else if(node_ptr->getLeftChildPtr() == nullptr)
{
return node_ptr->getRightChildPtr();
}
else if(node_ptr->getRightChildPtr() == nullptr)
{
return node_ptr->getLeftChildPtr();
}
else
{
T new_node_value;
node_ptr->setRightChildPtr(removeLeftmostNode(node_ptr->getRightChildPtr(), new_node_value));
node_ptr->setItem(new_node_value);
return node_ptr;
}
}
template<class T>
auto Roster<T>::removeLeftmostNode(std::shared_ptr<BinaryNode<T>> nodePtr, T& inorderSuccessor)
{
if(nodePtr->getLeftChildPtr() == nullptr)
{
inorderSuccessor = nodePtr->getItem();
return removeNode(nodePtr);
}
else
{
nodePtr->setLeftChildPtr(removeLeftmostNode(nodePtr->getLeftChildPtr(), inorderSuccessor));
return nodePtr;
}
}
template<class T>
void Roster<T>::inorder(Visitor<T>& visit, std::shared_ptr<BinaryNode<T>> tree_ptr) const
{
if(tree_ptr != nullptr)
{
inorder(visit, tree_ptr->getLeftChildPtr());
T the_item = tree_ptr->getItem();
visit(the_item);
inorder(visit, tree_ptr->getRightChildPtr());
}
}
//Operator Overloading for students objects
bool operator <(const Student& a, const Student& b)
{
if( a.getLastName() < b.getLastName())
{
return true;
}
else if(a.getLastName() == b.getLastName())
{
if(a.getFirstName() < b.getFirstName())
{
return true;
}
}
return false;
}
bool operator >(const Student& a, const Student& b)
{
if( a.getLastName() > b.getLastName())
{
return true;
}
else if(a.getLastName() == b.getLastName())
{
if(a.getFirstName() > b.getFirstName())
{
return true;
}
}
return false;
}
bool operator ==(const Student& a, const Student& b)
{
return (a.getFirstName() == b.getFirstName() && a.getLastName() == b.getLastName());
}
Current Roster.hpp:
#ifndef ROSTER_HPP
#define ROSTER_HPP
#include "BinaryNode.hpp"
#include "Visitor.hpp"
#include "Student.hpp"
#include "Printer.hpp"
#include <vector>
#include <memory>
class Roster
{
public:
Roster(); // Constructor
Roster(const Roster& tree); //Copy constructor
~Roster(); // Destructor
bool isEmpty() const;
int getHeight() const;
int getNumberOfNodes() const;
void add(const Student& new_item);
void add(const std::vector<Student>& new_items);
void remove(const Student& target);
void display();
Student find(const Student& item);
void clear();
void inorderTraverse(Visitor<Student>& visit) const;
Roster& operator= (const Roster& rhs);
private:
std::shared_ptr<BinaryNode<Student>> root_ptr_;
std::shared_ptr<BinaryNode<Student>> copyTree(const std::shared_ptr<BinaryNode<Student>> old_tree_root_ptr) const;
void destroyTree(std::shared_ptr<BinaryNode<Student>> sub_tree_ptr);
int getHeightHelper(std::shared_ptr<BinaryNode<Student>> sub_tree_ptr) const;
auto placeNode(std::shared_ptr<BinaryNode<Student>> sub_tree_ptr, std::shared_ptr<BinaryNode<Student>> new_node_ptr);
auto removeValue(std::shared_ptr<BinaryNode<Student>> sub_tree_ptr, const Student target);
auto removeNode(std::shared_ptr<BinaryNode<Student>> node_ptr);
auto removeLeftmostNode(std::shared_ptr<BinaryNode<Student>> nodePtr, Student& inorderSuccessor);
void inorder(Visitor<Student>& visit, std::shared_ptr<BinaryNode<Student>> tree_ptr) const;
//Operator overloading for students objects
friend bool operator <(const Student& a, const Student& b);
friend bool operator >(const Student& a, const Student& b);
friend bool operator ==(const Student& a, const Student& b);
};
#endif
Error:
declaration is incompatible with <error-type>
Roster::removeNode(std::__1::shared_ptr<BinaryNode<Student>> node_ptr)
Upvotes: 0
Views: 10888
Reputation: 4713
In the template case your implementation (.cpp) is a part of the header. In your current implementation - .cpp is not part of the header. Thus your auto
return types cannot be deduced by compiler whenever someone includes only the header. You ought to declare the return type.
Upvotes: 0