0

This is a General Trees program, where I am trying to find the depth of the tree (depth of 2) and calculate the size of the directory. The two errors are declaration errors (towards the bottom of Tree.cpp) and can't seem to declare the function properly.

Tree.cpp

#include "Tree.h"
#include <iostream>
using namespace std;

template <typename E>
bool Tree<E>::Position::isRoot() const
{
   if (u->parent == NULL)
       return true;
else
    return false;
}

template <typename E>
bool Tree<E>::Position::isExternal() const
{
    return (u->child.empty());

}

template <typename E>
bool Tree<E>::Position::operator==(Tree<E>::Position p)
{
    if (u == p.u)
        return true;
    else
        return false;
}

template <typename E>
Tree<E>::Position::Position(TreeNode *v)
{
    u = v;
}

template <typename E>
typename Tree<E>::Position Tree<E>::Position::parent()
{
    return Tree<E>::Position(u->parent);

}

template <typename E>
typename Tree<E>::PositionList Tree<E>::Position::children()
{
    return (u->child);

}

template <typename E>
E Tree<E>::Position::operator*()
{
    return u->e;
}

template <typename E>
typename Tree<E>::Position Tree<E>::root() 
{
    return typename Tree<E>::Position(r);
}

template <typename E>
int Tree<E>::size() const
{
    return this->n;
}

template <typename E>
bool Tree<E>::empty() const
{
    return size() == 0;
}

template <typename E>
void Tree<E>::insert(E e, Tree<E>::Position p)
{
    TreeNode *v = new TreeNode() ;
    v->e = e;
    if (empty())
        v->parent = NULL;
    else
        v->parent = p.u;
    if (!empty() )
    {
        p.u->child.insertBack(v);
    }
    else
    {
        v->parent = NULL;
        r = v;
    }
    ++n;
}

template <typename E>
NodeList<typename Tree<E>::Position>  Tree<E>::Positions()
{
    typename Tree<E>::PositionList list;
    preorder(r, list);
    return list;
}

template <typename E>
void Tree<E>::preorder(Tree<E>::Position  p, Tree<E>::PositionList &pl)
{
    pl.insertBack(p);
    if (p.u->child.empty()==false)
        for(typename Tree<E>::PositionList::Iterator ii = p.u->child.begin(); ii!= p.u->child.end(); ++ii)
        preorder(*ii, pl);
}

template <typename E>
int Tree<E>::depth(Tree<E>::TreeNode& u, Tree<E>::Position& p) //ERROR: Out-of-line definition of 'depth' does not match any declaration in 'Tree<E>' 
{
    if (p.isRoot())
        return 0;
    else
        return 1+depth(u, p.parent());
}


template <typename E>
int Tree<E>::directorySize(Tree<E>::TreeNode& u, Tree<E>::Position& p) //Out-of-line definition of 'directorySize' does not match any declaration in 'Tree<E>'
{
    int s = size(p);
    if (!p.isExternal())
    {
        PositionList ch = p.children();
        for (typename Tree<E>::PositionList::Iterator q = ch.begin(); q != ch.end(); q++)
            s += depth(u, *q);
        cout << name(p) << ": " << s << endl;
}
return s;
}

Tree.h

#ifndef TREE_H
#define TREE_H
#include <cstdlib>
#include "NodeList.cpp"


template <typename E>
class Tree {

public:
    class TreeNode; 

public:
    class Position                 // a node position
    {

    public:
        E operator*();                // get element
        Position parent();
        NodeList<Position> children();
        bool isRoot() const;             // root node?
        bool isExternal() const;             // external node?
        bool operator==(Position p);

        int depth(const Tree& u, const Position& p); //DECLARED(ERROR) - DEPTH OF TWO FUNCTION

        Position(typename Tree<E>::TreeNode *v);
        Position(){}

        typename Tree<E>::TreeNode *u;
        friend class NodeList<Position>;


    };

    typedef NodeList<typename Tree<E>::Position> PositionList;

public:
    class TreeNode
    {
        E e;
        TreeNode *parent;
        typename Tree<E>::PositionList child;
        friend class Tree;
        friend class Tree<E>::Position;

    public:
        TreeNode(){
            parent = NULL;
        }
        TreeNode(E,Tree<E>::Position*, Tree<E>::PositionList*);
        TreeNode& operator=(const TreeNode &t)
        {
            parent = t.parent;
            child = t.child;
            e = t.e;
        }

     };
public:                    // public functions of Tree
    Tree<E>(){
         n = 0;
    }
    int size() const;                // number of nodes
    bool empty() const;                // is tree empty?

    int directorySize(const TreeNode& u, const Position& p); //DECLARED(ERROR) - SIZE OF DIRECTORY

    Position root();
    PositionList Positions();

    void insert(E e, Position p);
    void preorder(Position p ,PositionList &pre_order);

 private:
    TreeNode *r;
    int n;
    friend class Position;
 };


#endif

The error is only showing up in the Tree.cpp file.

  • 1
    Possible duplicate of [Why can templates only be implemented in the header file?](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – Algirdas Preidžius Nov 26 '18 at 23:54
  • This doesn't addres the question, but instead of `if (something == something_else) return true; else return false;` you can write `return something == something_else;`. – Pete Becker Nov 26 '18 at 23:57
  • `#include "NodeList.cpp"` is almost always a bad idea. Include header files. Compile and link cpp files. All manner of bad smurf can happen if your build system spots the cpp file that you want included and links it instead. Plus it violates the Law of Least Surprise among those who expect a cpp file to be compiled and linked rather than included. – user4581301 Nov 27 '18 at 00:19
  • By the way, where is NodeList.cpp? Looks like it should be in the question for completeness if nothing else. Can't build your code and hunting the error is harder without it. – user4581301 Nov 27 '18 at 00:21

1 Answers1

0

There are multiple errors here:

  1. The arguments are declared to be const qualified references but the const got dropped in the definitions.
  2. depth() is a member of Tree<E>::Position not of Tree<E>.
  3. The first parameter of depth() is a Tree<E> not a TreeNode.

Note that putting the code into a .cpp file is either confusion (if the intention is to include the file) or it will cause grief when using the template classes from another translation unit. This problem is unrelated to the question, though.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • I fixed the header. I changed the depth to: int Tree::depth(const Tree&u, const Tree::Position& p). And for the directorySize function: int Tree::directorySize(const Tree& u, const Tree::Position& p). This declared the function properly, but in the end I made both function a standalone function rather than inserting it in the Tree.cpp file. – anonymous_s Nov 27 '18 at 18:54