When trying to compile I get the error: Error C2280 'std::variant<Tree::Position<int>,Tree::Position<std::string>,Tree::Position<double>,Tree::Position<bool>>::variant(const std::variant<Tree::Position<int>,Tree::Position<std::string>,Tree::Position<double>,Tree::Position<bool>> &)': attempting to reference a deleted function
I have a Tree class with a template sub-class Position. When using the load function of the Tree class, an instance of the Position class is added to the Tree's treePositionList. Also in the constructor function of the Position class an instance of the Position class is added to its childenList. I think the problem is related to the adding of an instance to those lists, though I do not understand what goes wrong exactly.
template <typename E>
class Node {
private:
string column;
E element;
public:
Node(E el, string col) { element = el; column = col;}
};
class Tree {
public:
template <typename E>
class Position {
private:
typedef variant<Position<int>, Position<string>, Position<double>, Position<bool>> Position_ManyTypes;
typedef list<Position_ManyTypes> PositionList;
Node<E>* node;
PositionList childrenList;
public:
Position(Tree* tree, const E element, const string column, const Json::Value &children);
Position(Position<E>& position);
~Position();
Position<E>& operator=(const Position<E> &position);
friend class Tree;
};
typedef variant<Position<int>, Position<string>, Position<double>, Position<bool>> Position_ManyTypes;
typedef list<Position_ManyTypes> PositionList;
Tree() {}
bool load(string filename);
private:
PositionList treePositionList;
};
bool Tree::load(string filename) {
ifstream rules_file(filename, ifstream::in);
Json::Value rules;
rules_file >> rules;
rules_file.close();
Position<string> root_position = Position<string>(this, "string123", "string456", rules["children"]);
treePositionList.push_back(root_position);
return true;
}
template <typename E>
Tree::Position<E>::Position(Tree::Position<E>& position) {
node = position.node;
childrenList = position.childrenList;
}
template <typename E>
Tree::Position<E>& Tree::Position<E>::operator=(const Tree::Position<E>& position) {
if (this != &position) {
delete node;
node = position.node;
childrenList = position.childrenList;
}
return *this;
}
template <typename E>
Tree::Position<E>::~Position() {
delete node;
}
template <typename E>
Tree::Position<E>::Position(Tree* tree, const E el, const string col, const Json::Value &children) {
node = new Node<E>(el, col);
Position<string> pos = Position<string>(tree, "string123", "string456", children[0]["children"]);
childrenList.push_back(pos);
}
Related
I have two classes representing a graph:
class Node {
public:
void AppendSource(Edge &Edge) { m_Sources.append(&Edge); }
void AppendSink(Edge &Edge) { m_Sinks.append(&Edge); }
QList<Edge *> &Sources() { return m_Sources; }
QList<Edge *> &Sinks() { return m_Sinks; }
QList<Edge *> const &Sources() const { return m_Sources; }
QList<Edge *> const &Sinks() const { return m_Sinks; }
protected:
QList<Edge *> m_Sources;
QList<Edge *> m_Sinks;
}; // Node
class Edge {
public:
Edge(Node &Source, Node &Sink) : m_pSource(&Source), m_pSink(&Sink) {}
Node const &Source() const { return *m_pSource; }
Node const &Sink() const { return *m_pSink; }
Node &Source() { return *m_pSource; }
Node &Sink() { return *m_pSink; }
void SetSource(Node &Source) { m_pSource = &Source; }
void SetSink(Node &Sink) { m_pSink = &Sink; }
protected:
Node *m_pSource;
Node *m_pSink;
}; // Edge
It should be possible to inherit from these classes, in order to add functionality for specific types of graphs. Therefore, the classes should be template classes:
template <class EDGE_TYPE>
class Node {
public:
void AppendSource(EDGE_TYPE &Edge) { m_Sources.append(&Edge); }
void AppendSink(EDGE_TYPE &Edge) { m_Sinks.append(&Edge); }
QList<EDGE_TYPE *> &Sources() { return m_Sources; }
QList<EDGE_TYPE *> &Sinks() { return m_Sinks; }
QList<EDGE_TYPE *> const &Sources() const { return m_Sources; }
QList<EDGE_TYPE *> const &Sinks() const { return m_Sinks; }
protected:
QList<EDGE_TYPE *> m_Sources;
QList<EDGE_TYPE *> m_Sinks;
}; // Node
template <class NODE_TYPE>
class Edge {
public:
Edge(NODE_TYPE &Source, NODE_TYPE &Sink) : m_pSource(&Source), m_pSink(&Sink) {}
NODE_TYPE const &Source() const { return *m_pSource; }
NODE_TYPE const &Sink() const { return *m_pSink; }
NODE_TYPE &Source() { return *m_pSource; }
NODE_TYPE &Sink() { return *m_pSink; }
void SetSource(NODE_TYPE &Source) { m_pSource = &Source; }
void SetSink(NODE_TYPE &Sink) { m_pSink = &Sink; }
protected:
NODE_TYPE *m_pSource;
NODE_TYPE *m_pSink;
}; // Edge
But now it seems no longer possible to use the classes without extending them! A few attempts with the obvious corresponding errors:
new Node(); // 'Node': use of class template requires template argument list
new Node<>(); // 'Node': too few template arguments
new Node<Edge>(); // 'Edge': unspecialized class template can't be used as a template argument for template parameter 'EDGE_TYPE', expected a real type
new Node<Edge<>>(); // 'Edge': too few template arguments
new Node<Edge<Node>>(); // 'Node': unspecialized class template can't be used as a template argument for template parameter 'NODE_TYPE', expected a real type
new Node<Edge<Node<>>>(); // 'Node': too few template arguments
I was hoping to solve this by introducing defaults for the template arguments. A few attempt with their corresponding errors:
template <class EDGE_TYPE = Edge>
class Node { ... }
template <class NODE_TYPE = Node>
class Edge { ... }
new Node<>(); // 'Edge': unspecialized class template can't be used as a template argument for template parameter 'EDGE_TYPE', expected a real type
template <class EDGE_TYPE = Edge<>>
class Node { ... }
template <class NODE_TYPE = Node<>>
class Edge { ... }
new Node<>(); // recursive type or function dependency context too complex
template <class EDGE_TYPE = Edge<Node<EDGE_TYPE>>>
class Node { ... }
template <class NODE_TYPE = Node<Edge<NODE_TYPE>>>
class Edge { ... }
new Node<>(); // 'EDGE_TYPE': undeclared identifier
How can I make Node and Edge both directly usable and extensible though inheritance?
How can I make Node and Edge both directly usable and extensible
though inheritance?
I'll focus on that requirement in bold.
Though you can have the definition of Edge and Node depend on each other, there's no way to make recurring declaration of Edge and Node, because such declaration would yield infinite template recursion:
Node<> = Node<Edge<>> = Node<Edge<Node<>>> = Node<EdgeNode<Edge<>>>> ...
So, if you want Edge<> and Node<> to be directly usable (i.e. instantiateable without making dummy derived classes), then you should break that recursion. For example, by making both Edge and Node depend on some third traits class:
// Forward declaration.
struct DefaultGraphTypes;
template <typename GraphTypes = DefaultGraphTypes>
struct Node;
template <typename GraphTypes = DefaultGraphTypes>
struct Edge;
// Traits class.
template <typename NodeT, typename EdgeT>
struct GraphTypes
{
// Could change this to 'using' in modern C++
typedef NodeT FinalNodeType;
typedef EdgeT FinalEdgeType;
// typedef MayBeSomeOtherParameters ...
};
struct DefaultGraphTypes
: public GraphTypes<Node<DefaultGraphTypes>, Edge<DefaultGraphTypes>>
{
};
// Implementation of graph classes.
template <typename GraphTypes>
struct Node
{
typedef typename GraphTypes::FinalNodeType FinalNodeType;
typedef typename GraphTypes::FinalEdgeType FinalEdgeType;
// ... Your implementation
};
template <typename GraphTypes>
struct Edge
{
typedef typename GraphTypes::FinalNodeType FinalNodeType;
typedef typename GraphTypes::FinalEdgeType FinalEdgeType;
// ... Your implementation
};
// User-derived types.
struct MyNode;
struct MyEdge;
struct MyNode
: public Node<GraphTypes<MyNode, MyEdge>>
{
// Something specific
};
struct MyEdge
: public Edge<GraphTypes<MyNode, MyEdge>>
{
// Something specific
};
// Test
int main()
{
Node<> n1;
Edge<> e1;
MyNode n2;
MyEdge e2;
return 0;
}
IMHO, this can be achieved by inserting forward declarations at the right place. I took parts of OP sample code and completed it to a compilable sample:
#include <iostream>
#include <vector>
#define QList std::vector // Sorry, no Qt at hand in coliru
template <class EDGE_TYPE>
class Node {
public:
void AppendSource(EDGE_TYPE &Edge) { m_Sources.append(&Edge); }
void AppendSink(EDGE_TYPE &Edge) { m_Sinks.append(&Edge); }
QList<EDGE_TYPE *> &Sources() { return m_Sources; }
QList<EDGE_TYPE *> &Sinks() { return m_Sinks; }
QList<EDGE_TYPE *> const &Sources() const { return m_Sources; }
QList<EDGE_TYPE *> const &Sinks() const { return m_Sinks; }
protected:
QList<EDGE_TYPE *> m_Sources;
QList<EDGE_TYPE *> m_Sinks;
}; // Node
template <class NODE_TYPE>
class Edge {
public:
Edge(NODE_TYPE &Source, NODE_TYPE &Sink) : m_pSource(&Source), m_pSink(&Sink) {}
NODE_TYPE const &Source() const { return *m_pSource; }
NODE_TYPE const &Sink() const { return *m_pSink; }
NODE_TYPE &Source() { return *m_pSource; }
NODE_TYPE &Sink() { return *m_pSink; }
void SetSource(NODE_TYPE &Source) { m_pSource = &Source; }
void SetSink(NODE_TYPE &Sink) { m_pSink = &Sink; }
protected:
NODE_TYPE *m_pSource;
NODE_TYPE *m_pSink;
}; // Edge
// forward declarations:
struct WNode;
struct WEdge;
// declaration of derived types
struct WNode: public Node<WEdge>
{
int weight;
};
struct WEdge: public Edge<WNode>
{
int weight;
WEdge(WNode &src, WNode &snk): Edge(src, snk) { }
};
// check whether it compiles
int main()
{
WNode node1, node2;
WEdge edge12(node1, node2);
// done
return 0;
}
Live Demo on coliru
That's the actual trick:
OP carefully used in template class Node and template class Edge only references and pointers to the resp. opposite type. Hence, an incomplete type is fully sufficient to be used as template argument in both cases. These incomplete types are provided by the forward declarations:
// forward declarations:
struct WNode;
struct WEdge;
Afterwards, the classes WNode and WEdge can be derived from Node<WEdge> and Edge<WNode>.
template template parameter might help:
template <typename TEdge>
class Node {
public:
using EDGE_TYPE = TEdge;
void AppendSource(EDGE_TYPE &Edge) { m_Sources.append(&Edge); }
void AppendSink(EDGE_TYPE &Edge) { m_Sinks.append(&Edge); }
QList<EDGE_TYPE *> &Sources() { return m_Sources; }
QList<EDGE_TYPE *> &Sinks() { return m_Sinks; }
QList<EDGE_TYPE *> const &Sources() const { return m_Sources; }
QList<EDGE_TYPE *> const &Sinks() const { return m_Sinks; }
protected:
QList<EDGE_TYPE *> m_Sources;
QList<EDGE_TYPE *> m_Sinks;
}; // Node
template <template <typename> class TNode>
class Edge {
public:
using NODE_TYPE = TNode<Edge>; // which is TNode<Edge<TNode>>
Edge(NODE_TYPE &Source, NODE_TYPE &Sink) : m_pSource(&Source), m_pSink(&Sink) {}
NODE_TYPE const &Source() const { return *m_pSource; }
NODE_TYPE const &Sink() const { return *m_pSink; }
NODE_TYPE &Source() { return *m_pSource; }
NODE_TYPE &Sink() { return *m_pSink; }
void SetSource(NODE_TYPE &Source) { m_pSource = &Source; }
void SetSink(NODE_TYPE &Sink) { m_pSink = &Sink; }
protected:
NODE_TYPE *m_pSource;
NODE_TYPE *m_pSink;
};
Then you might have:
using MyEdge = Edge<Node>;
using MyNode = Node<Edge<Node>>; // Node<MyEdge>
or even:
template <template <typename> class TNode>
class CustomEdge : Edge<TNode> {
// ...
};
using MyNode2 = Node<CustomEdge>;
using MyEdge2 = CustomEdge<Node>;
Demo
This is a function to find the maximum amount of left nodes. I do realize that there is already a thread for that:
Count number of left nodes in BST
but I don't want pointers in my main file. So I am trying to find a slightly different approach.
bst<int>::binTreeIterator it;
int findMax(bst<int>::binTreeIterator it)
{
int l = 0, r;
if (!(it.leftSide() == NULL)) {
l += 1 + findMax(it.leftSide());
}
if (!(it.rightSide() == NULL)) {
r = findMax(it.rightSide());
}
return l;
}
my problem is with the leftSide()/rightSide() function; How do I implement them so that it returns an iterator object that points to the left side/ right side of the iterator "it" object?
template <class Type>
typename bst<Type>::binTreeIterator bst<Type>::binTreeIterator::leftSide()
{
}
Edit:
template <class Type>
class bst
{
struct binTreeNode
{
binTreeNode * left;
binTreeNode * right;
Type item;
};
public:
class binTreeIterator
{
public:
friend class bst;
binTreeIterator();
binTreeIterator(binTreeNode*);
bool operator==(binTreeNode*);
bool operator==(binTreeIterator);
binTreeIterator rightSide();
binTreeIterator leftSide();
private:
binTreeNode * current;
};
bst();
bst(const bst<Type>&);
const bst& operator=(const bst<Type>&);
~bst();
void insert(const Type&);
void display(); // TEST
binTreeIterator begin();
binTreeIterator end();
private:
binTreeNode * insert(binTreeNode*, const Type&);
void inorder(binTreeNode*);
void destroyTree(binTreeNode*);
void cloneTree(binTreeNode*, binTreeNode*);
binTreeNode * root;
};
This very simple snipped of code should do the trick already:
template <class Type>
typename bst<Type>::binTreeIterator bst<Type>::binTreeIterator::leftSide()
{
return current->left;
}
As you did not declare the iterator's constructor explicit, it will get called automatically from the pointer to left/right returned.
I'm trying to work on an assignment where the professor has requested that the iterator for a Linked List has to be a separate header file.
However, all implementations I've seen of Iterators I've seen have the definition of the class inside of the bag/list class. So I have no idea how to create an iterator within the bag like
dlist<int>::iterator it1
without defining it inside the list.
For reference, here are my list, node, and iterator classes as is:
dnode.h
template <class T>
class dnode{
public:
dnode(){
linknext = NULL;
prevlink = NULL;
}
void set_data(T item){data_value = item;}
void set_next(dnode<T> *link){linknext = link;}
void set_prev(dnode<T> *link){prevlink = link;}
T data()const{return data_value;}
dnode *next(){return linknext;}
dnode *prev(){return prevlink;}
private:
dnode *linknext;
dnode *prevlink;
T data_value;
};
dlist.h
#include "dnode.h"
#include "iterator.h"
template <class T>
class dlist{
public:
dlist(){head = tail = NULL;}
void rear_insert(T data);
void front_insert(T data);
void front_remove();
void rear_remove();
void reverse_show();
void show();
iterator<T> begin(){return iterator<T>(head);}
iterator<T> end(){return iterator<T>(tail);}
iterator<T> r_begin(){return iterator<T>(tail);}
iterator<T> r_end(){return iterator<T>(head);}
void insert_after(iterator<T>& current,T item){
dnode<T>* tmp;
tmp = new dnode<T>;
current.get_dnode()->next()->set_prev(tmp);
tmp->set_data(item);
tmp->set_next(current.get_dnode()->next());
tmp->set_prev(current.get_dnode());
current.get_dnode()->set_next(tmp);
}
void insert_before(iterator<T>& current,T item){
dnode<T>* tmp;
tmp = new dnode<T>;
current.get_dnode()->prev()->set_next(tmp);
tmp->set_data(item);
tmp->set_next(current.get_dnode());
tmp->set_prev(current.get_dnode()->prev());
current.get_dnode()->set_prev(tmp);
}
friend class iterator<T>;
private:
dnode<T> *head;
dnode<T> *tail;
};
iterator.h
template <class T>
class iterator
{
public:
iterator(dnode<T> *first = NULL){current = first;}
dnode<T>* get_dnode(){return current;}
T& operator *()const{return current->data();}
iterator& operator ++(){
current = current->next();
return *this;
}
iterator& operator ++(int){
iterator original(current);
current = current->next();
return original;
}
iterator& operator --(){
current = current->prev();
return *this;
}
iterator& operator --(int){
iterator original(current);
current = current->prev();
return original;
}
bool operator ==(const iterator something)const{ return current == something.current;}
bool operator !=(const iterator something)const{ return current == something.current;}
private:
dnode<T> *current;
};
Thanks for any assistance.
You can declare the iterator and node types within the list class but define them elsewhere. The syntax you need is of the form as follows:
template <class T>
class list {
public:
class iterator;
struct node;
node* head;
iterator begin()
{
return head;
}
iterator end()
{
return head->prev;
}
};
template <class T>
class list<T>::iterator {
node* pos;
public:
iterator(node* p) : pos (p) { }
// ...
};
template <class T>
struct list<T>::node {
node* next;
node* prev;
// ...
};
void f()
{
list<int> l;
list<int>::iterator i = l.begin();
list<int>::node n;
}
When inside the definition of list, node or iterator you should no longer need the list:: prefix. Outside (which includes return types on functions defined outside those classes) you do need the list:: prefix.
In this form your include structure will be the reverse of what you have above where list.h does not need to include node.h or iterator.h but both of those files will include list.h. You might want to include node.h and iterator.h at the end of list.h so that users of your class can get all the definitions by including list.h.
**Be careful**, not only does this program hang, but apparently it takes all of your memory forever, rendering your computer a slow and awful mess. I've been struggling with this for a real long time, and have figured out a lot of things—except for why it actually hangs. Sorry that there's so much code, but I cut out everything irrelevant and this is what was left.
LinkedList
//=====================
// Linked List
#include <stdexcept>
template<class T> struct LinkedList {
public:
LinkedList();
LinkedList(const LinkedList& srcList);
~LinkedList();
void addObject (T& addedObject);
class ListIterator {
public:
ListIterator();
explicit ListIterator(LinkedList<T>& parentList);
// Operators
ListIterator& operator++();
T& operator*() const;
bool operator!=(const ListIterator& otherIter);
private:
typename LinkedList::Node* current_;
};
ListIterator begin();
ListIterator end();
std::size_t size_;
private:
struct Node {
Node();
Node(T& object);
Node(const Node&) = delete;
T* const object_;
Node* next_;
Node* prev_;
};
Node head_;
Node tail_;
};
//====================
// Classes (Implementation)
// Linked List default constructor
template<class T> LinkedList<T>::LinkedList()
: size_{0} {
head_.next_ = &tail_;
tail_.prev_ = &head_;
};
// Linked List copy constructor
template<class T> LinkedList<T>::
LinkedList(const LinkedList& srcList) {
size_ = srcList.size_;
head_.next_ = &tail_;
tail_.prev_ = &head_;
ListIterator nodesToCopy = srcList.begin();
while (nodesToCopy != srcList.end()) {
this->addObject(*nodesToCopy);
srcList.removeObject(1);
};
delete &srcList;
};
// Linked List destructor
template<class T> LinkedList<T>::~LinkedList() {
for (unsigned int ii = 1; ii == size_; ++ii) {
Node* toDelete = head_.next_;
head_.next_ = head_.next_->next_;
delete toDelete;
};
};
// Add object to Linked List
template<class T> void LinkedList<T>::addObject(T& addedObject) {
Node* node = new Node(addedObject);
node->prev_ = tail_.prev_;
tail_.prev_->next_ = node;
tail_.prev_ = node;
node->next_ = &tail_;
++size_;
};
// Linked List Iterator constructor
template<class T> LinkedList<T>::ListIterator::
ListIterator(LinkedList<T>& parentList) {
current_ = parentList.head_.next_;
};
// Iterator operators
// Increment forward
template<class T> typename LinkedList<T>::ListIterator& LinkedList<T>::
ListIterator::operator++() {
current_ = current_->next_;
return *this;
};
// Return object pointed to
template<class T> T& LinkedList<T>::ListIterator::
operator*() const {
return *(current_->object_);
};
template<class T> bool LinkedList<T>::ListIterator::
operator!=(const ListIterator& otherIter) {
return &(**this) != &(*otherIter);
};
// Return an iterator object via begin() and end()
template<class T> typename LinkedList<T>::ListIterator
LinkedList<T>::begin() {
ListIterator beginIterator(*this);
return beginIterator;
};
template<class T> typename LinkedList<T>::ListIterator
LinkedList<T>::end() {
ListIterator endIterator(*this);
for (unsigned int ii = 0; ii < size_; ++ii) { ++endIterator; };
return endIterator;
};
// Node constructors
template<class T> LinkedList<T>::Node::Node()
: object_(nullptr), next_(nullptr), prev_(nullptr) {};
template<class T> LinkedList<T>::Node::Node(T& object)
: object_(&object) {};
Item
//=====================
// Item
//====================
// Included dependencies
#include <string>
#include <array>
#include <map>
#include <iostream>
class Item {
public:
Item();
Item(std::string name);
Item(std::string name, std::array<int, 2> stats);
std::map<std::string, int> getStats();
std::string name_;
private:
std::map<std::string, int> enhancements_;
};
// Constructors
Item::Item() {
enhancements_["Str"] = 0;
enhancements_["Def"] = 0;
};
Item::Item(std::string name) : Item::Item() { name_ = name; };
Item::Item(std::string name, std::array<int, 2> stats)
: Item::Item(name) {
enhancements_["Str"] = stats[0];
enhancements_["Def"] = stats[1];
};
// Return map of stats
std::map<std::string, int> Item::getStats() { return enhancements_; };
Room
//====================
// Room
class Room {
public:
void addItem(Item item);
LinkedList<Item>::ListIterator getItems();
LinkedList<Item> itemsInThisRoom_;
};
// Add item to room
void Room::addItem(Item item) { itemsInThisRoom_.addObject(item); };
// Get iterator which iterates over items in room
LinkedList<Item>::ListIterator Room::getItems() {
return itemsInThisRoom_.begin();
};
main
int main() {
std::array<int, 2> swordStats = {{5, 0}};
std::array<int, 2> shieldStats = {{0, 2}};
std::array<int, 2> armorStats = {{0, 3}};
Item sword("Sword", swordStats);
Item shield("Shield", shieldStats);
Item armor("Armor", armorStats);
Room room;
room.addItem(shield);
room.addItem(sword);
room.addItem(armor);
LinkedList<Item>::ListIterator roomItems = room.itemsInThisRoom_.begin();
while (roomItems != room.itemsInThisRoom_.end()) {
(*roomItems).getStats();
++roomItems;
};
return 0;
};
All of this can be put in a single file and compiled (I split it up by class to make it easier to read). This is the line, in main, where it hangs:
(*roomItems).getStats();
This leads me to believe there's something wrong with my dereference operator, right? If we create an iterator outside of the Room class, dereference it, and getStats the same way—everything works ok.
... so it's an issue with the Room class?
But, if we change Item and main to the following:
//=====================
// Item
//====================
// Included dependencies
#include <string>
#include <array>
#include <map>
#include <iostream>
class Item {
public:
Item();
Item(std::string name);
Item(std::string, int);
int getStats();
std::string name_;
private:
int enhancements_;
};
// Constructors
Item::Item() {
enhancements_ = 0;
};
Item::Item(std::string name) : Item::Item() { name_ = name; };
Item::Item(std::string name, int stats)
: Item::Item(name) {
enhancements_ = stats;
};
// Return map of stats
int Item::getStats() { return enhancements_; };
//====================
// Room
class Room {
public:
void addItem(Item item);
LinkedList<Item>::ListIterator getItems();
LinkedList<Item> itemsInThisRoom_;
};
// Add item to room
void Room::addItem(Item item) { itemsInThisRoom_.addObject(item); };
// Get iterator which iterates over items in room
LinkedList<Item>::ListIterator Room::getItems() {
return itemsInThisRoom_.begin();
};
int main() {
Item sword("Sword", 1);
Item shield("Shield", 2);
Item armor("Armor", 3);
Room room;
room.addItem(shield);
room.addItem(sword);
room.addItem(armor);
LinkedList<Item>::ListIterator roomItems = room.itemsInThisRoom_.begin();
while (roomItems != room.itemsInThisRoom_.end()) {
(*roomItems).getStats();
++roomItems;
};
return 0;
};
Everything runs excellently. I can return int values alright.
... so... it's neither an issue with the Room class or the dereference operator, but returning std::map? GDB does not have much to say. When I break at the offending line and step, I get:
24 std::map<std::string, int> Item::getStats() { return enhancements_; };
(gdb) step
_Rb_tree_impl (__a=<optimized out>, __comp=..., this=0x7fffffffced0)
at /usr/include/c++/4.9/bits/stl_tree.h:474
474 _M_header(), _M_node_count(0)
(gdb) step
475 { _M_initialize(); }
(gdb) step
_M_initialize (this=0x7fffffffced0)
at /usr/include/c++/4.9/bits/stl_tree.h:484
484 this->_M_header._M_left = &this->_M_header;
(gdb) step
485 this->_M_header._M_right = &this->_M_header;
(gdb) step
_Rb_tree (__x=..., this=0x7fffffffced0)
at /usr/include/c++/4.9/bits/stl_tree.h:674
674 if (__x._M_root() != 0)
(gdb) step
_M_root (this=0x7fffffffd048)
at /usr/include/c++/4.9/bits/stl_tree.h:498
498 { return this->_M_impl._M_header._M_parent; }
(gdb) step
_Rb_tree (__x=..., this=0x7fffffffced0)
at /usr/include/c++/4.9/bits/stl_tree.h:674
674 if (__x._M_root() != 0)
(gdb) step
676 _M_root() = _M_copy(__x._M_begin(), _M_end());
(gdb) step
std::_Rb_tree<std::string, std::pair<std::string const, int>, std::_Select1st<std::pair<std::string const, int> >, std::less<std::string>, std::allocator<std::pair<std::string const, int> > >::_M_copy (
this=this#entry=0x7fffffffced0, __x=0x619f10,
__p=__p#entry=0x7fffffffced8)
at /usr/include/c++/4.9/bits/stl_tree.h:1207
1207 _Link_type __top = _M_clone_node(__x);
... which is gibberish to me. :( It does this infinitely, so I know that it (somehow) describes the hangup.
I've got no clue what's going on here, haha. I'm very new to C++, and have struggled with this since I woke, so for all I know my code is terrible and I should feel bad for writing it.
Any ideas?
In addition to what's already been mentioned, your Node object nonchalantly stores a pointer an object passed from outside by reference
template<class T> LinkedList<T>::Node::Node(T& object)
: object_(&object) {};
However, the reference arguments you pass to the constructor of Node are actually bound to local variables
template<class T> void LinkedList<T>::addObject(T& addedObject) {
Node* node = new Node(addedObject);
node->prev_ = tail_.prev_;
tail_.prev_->next_ = node;
tail_.prev_ = node;
node->next_ = &tail_;
++size_;
};
void Room::addItem(Item item) { itemsInThisRoom_.addObject(item); };
i.e. the reference is bound to parameter item which is a local variable inside addItem.
That local variable item is destroyed as soon as addItem exits. Your Node::object_ pointers remain pointing nowhere.
Considering the amount of gratuitous copying you perform in your code, it is completely unclear how you managed to come up with the idea to store a pointer to a non-owned object inside your Node (instead of gratuitously copying the entire data into the Node, as you do virtually everywhere else).
Anyway, the memory ownership is completely broken in your code, which leads to object lifetime issues as the one above. You need to design some meaningful memory ownership plan from scratch, and then write your code following that plan. What you have now is nonredeemable mess.
If you want to use pointers and you don't think you're ready to untangle this mess, just use smart pointers and let them handle things for you.
P.S. And drop that nasty habit of placing a ; after each and every }.
From template<class T> LinkedList<T>::LinkedList(const LinkedList& srcList)
delete &srcList;
Really? Just removing this line will improve your code. &srcList is not necessarily an address that has been allocated on the heap. And in any case a copy constructor should not be deleting the original.
From template<class T> LinkedList<T>::~LinkedList()
for (unsigned int ii = 1; ii == size_; ++ii)
This loop has no effect unless the size of the list is one, it should be
for (unsigned int ii = 0; ii < size_; ++ii)
So I've been playing around with Nodes and keep running into this error when I try to test it. If I use Parentheses I get this Error on list. - "Expression must have class type!"
If I don't use Parentheses I get this Error on list, insert and display - "this is inaccessible."
This happens when Declaring my LList in Main(). What's going on and why is this?
My Driver
#include "LList.h"
#include <iostream>
using namespace std;
int main()
{
LList<int> list;
bool test = list.insert(5);
list.display();
return 0;
}
Class LList
#include "Nodes.h"
#ifndef LLIST_H
#define LLIST_H
template<typename TYPE>
class LList
{
Node<TYPE>* front;
LList();
~LList();
bool insert(const TYPE& dataIn);
void display() const;
};
template<typename TYPE>
LList<TYPE>::LList()
{
front = null;
};
template<typename TYPE>
LList<TYPE>::~LList()
{
Node<TYPE>* temp;
while(front)
{
temp = front;
front = fornt -> next;
delete temp;
}
};
template<typename TYPE>
bool LList<TYPE>::insert(const TYPE& dataIn)
{
bool success = false;
Node<TYPE> pBefore = null;
Node<TYPE> pAfter = front;
while(pAfter && PAfter->data < dataIn)
{
pBefore = pAfter;
pAfter = pAfter->next;
}
if(Node<TYPE>* store = new Node<TYPE>)
store->data = dataIn
return success;
};
template<typename TYPE>
void LList<TYPE>::display() const
{
TYPE* temp = front;
while(front && temp->next != null)
{
cout << temp->data << endl;
}
};
#endif
Class Nodes
#ifndef NODES_H
#define NODES_H
template<typename TYPE>
struct Node
{
Node<TYPE>* next;
TYPE data;
Node();
Node(TYPE d, Node<TYPE> n);
};
template<typename TYPE>
Node<TYPE>::Node()
{
data = 0;
next = null;
};
template<typename TYPE>
Node<TYPE>::Node(TYPE d, Node<TYPE> n)
{
data = d;
next = n;
};
#endif
Your errors are a result of your class declaration:
template<typename TYPE>
class LList
{
Node<TYPE>* front;
LList();
~LList();
bool insert(const TYPE& dataIn);
void display() const;
};
The clue is in the error "This is inaccesible." Because you have not given any access modifiers, all of the members of this class default to private. To fix this, you just need to label the public and private sections of your class:
template<typename TYPE>
class LList
{
public:
LList();
~LList();
bool insert(const TYPE& dataIn);
void display() const;
private:
Node<TYPE>* front;
};
With this change, your code should work with or without parentheses at the end of your variable declaration for list.