1

When I try to compile this code, I get these errors from the Visual Studio compiler:

Error   C2447   '{': missing function header (old-style formal list?)   Binary Sarch Tree   127 

Error   C2061   syntax error: identifier 'Node' Binary Sarch Tree   127 

Error   C2143   syntax error: missing ';' before '{'    Binary Sarch Tree   127 

Line 127 is the implementation of Tree::find

HEADER FILE

#ifndef TREE_H
#define TREE_H

#include <iostream>
#include <limits>
#include <string>
#include <exception>

using namespace std;

class TreeException : public exception {
public:
    TreeException(string msg) noexcept;
    TreeException(const TreeException &src) noexcept;
    TreeException &operator= (const TreeException &src) noexcept;
    virtual ~TreeException();
    virtual const char* what() const noexcept;
    string msg;
};

const unsigned long custom_hash(const string &key);

template <class K, class C>
class Tree {
    struct Node {
        Node(const unsigned long hash, const K &key, 
            const C &container, const bool isDupl = false, 
            const Node *const parent = NULL);
        unsigned long hash;
        K key;
        C container;
        Node *parent, *left, *right, *dupl;
        bool isDupl;
    };
public:
    Tree();
    Tree(const Tree &src);
    ~Tree();
    void add(const K &key, const C &container);
    void remove(const K &key);
    C &get(const K &key);
    C &operator[](const K &key);
    const unsigned int size() const;

private:
    Node *const find(const K &key) const;
    void destruct(const Node *curr);
    Node *m_root;
};

#endif

IMPLEMENTATION FILE

#include "Tree.h"

//TreeException

TreeException::TreeException(string msg) noexcept
    : msg(msg)
{}

TreeException::TreeException(const TreeException &src) noexcept {
    msg = src.msg;
}

TreeException &TreeException::operator= (const TreeException &src) noexcept {
    msg = src.msg;
    return *this;
}

TreeException::~TreeException() {}

const char* TreeException::what() const noexcept {
    return msg.c_str();
}

//Common
const unsigned long custom_hash(const string &key) {
    unsigned long ret = 0;
    for (unsigned int i = 0; i < key.length(); i++)
        ret += key[i];
    for (unsigned int i = 0; i < key.length(); i++) {
        ret *= key[key[i] % key.length()];
        ret %= ULONG_MAX;
    }
    return ret;
}

//Tree::Node
template <class K, class C>
Tree<K, C>::Node::Node(const unsigned long hash, const K &key, 
    const C &container, const bool isDupl, 
    const Node *const parent)
    : hash(hash), key(key), 
    container(container), parent((Node*)parent),
    left(NULL), right(NULL),
    dupl(NULL), isDupl(false)
{}

//Tree
template <class K, class C>
Tree<K, C>::Tree()
    : m_root(NULL)
{}

template <class K, class C>
Tree<K, C>::Tree(const Tree &src) {

}

template <class K, class C>
Tree<K, C>::~Tree() {
    if (m_root)
        destruct(m_root);
}

template <class K, class C>
void Tree<K, C>::add(const K &key, const C &container) {
    const unsigned long h = custom_hash(key);
    if (!m_root)
        m_root = new Node(h, key, container);
    else {
        Node *curr = m_root;
        while (curr->hash != h) {
            if (h < curr->hash) {
                if (curr->left)
                    curr = curr->left;
                else
                    break;
            } else {
                if (curr->right)
                    curr = curr->right;
                else
                    break;
            }
        }
        if (curr->hash == h) {
            if (curr->key == key)
                throw TreeException("Key \"" + key + "\" already exists in the tree");
            while (curr->dupl) {
                curr = curr->dupl;
                if (curr->key == key)
                    throw TreeException("Key \"" + key + "\" already exists in the tree");
            }
            curr->dupl = new Node(h, key, container, true, curr);
        } else if (h < curr->hash) {
            curr->left = new Node(h, key, container, false, curr);
        } else {
            curr->right = new Node(h, key, container, false, curr);
        }
    }
}

template <class K, class C>
void Tree<K, C>::remove(const K &key) {

}

template <class K, class C>
C &Tree<K, C>::get(const K &key) {
    return find(key)->container;
}

template <class K, class C>
C &Tree<K, C>::operator[](const K &key) {
    try {
        return get(key);
    } catch (exception &e) {
        add(key, C());
        return get(key);
    }
}

template <class K, class C>
const unsigned int Tree<K, C>::size() const {

}

template <class K, class C>
Tree<K, C>::Node *const Tree<K, C>::find(const K &key) const {
    if (!m_root)
        throw TreeException("Tree is empty");
    const unsigned long h = custom_hash(key);
    Node *curr = m_root;
    while (curr->hash != h) {
        if (h < curr->hash) {
            if (curr->left)
                curr = curr->left;
            else
                break;
        }
        else {
            if (curr->right)
                curr = curr->right;
            else
                break;
        }
    }
    if (curr->>hash != h)
        throw TreeException("Key \"" + key + "\" couldn't be found");
    while (curr->key != key && curr->dupl)
        curr = curr->dupl;
    if (curr->key != key)
        throw TreeException("Key \"" + key + "\" couldn't be found");
    return curr;
}

template <class K, class C>
void Tree<K, C>::destruct(const Node *curr) {
    if (curr->left)
        destruct(curr->left);
    if (curr->right)
        destruct(curr->right);
    if (curr->dupl)
        destruct(curr->dupl);
    delete curr;
}

What could the problem be?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • `Tree::Node *const Tree::find(const K &key) const {` -> `typename Tree::Node *const Tree::find(const K &key) const {` – Mike Vine Nov 15 '19 at 00:52
  • In addition to the above, relevant reading: [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/495056); [Why is “using namespace std;” considered bad practice?](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) – Algirdas Preidžius Nov 15 '19 at 00:54
  • 2
    Since you know where the error occurs, perhaps you could trim down the code you're asking us to read through? A [mcve] would be more useful to us, and perhaps instructive to you. – JaMiT Nov 15 '19 at 00:55
  • And even after fixing this typo, this entire "implementation file" will be a complete and total failure, because C++ templates [can only be implemented in header files](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file). Did you know that? Add to this, the [`using namespace std;`, in a header file, no less](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice), and the shown code cannot be fixed. It is fundamentally flawed, and you will need to, pretty much, rewrite the whole thing from scratch. Sorry. – Sam Varshavchik Nov 15 '19 at 00:56
  • Thx a lot guys!!! – William Boulanger Nov 15 '19 at 00:56
  • But guys, i excluded the cpp file from compilation and included it in main.cpp. It works. – William Boulanger Nov 15 '19 at 01:00
  • 1
    @WilliamBoulanger if you mean you `#include`'d the `.cpp` file into `main.cpp`, then 1) all of the templated code ends up in a single translation unit, which is why it works; and 2) [don't `#include` `.cpp` files](https://stackoverflow.com/questions/45110783/) in normal situations – Remy Lebeau Nov 15 '19 at 03:08

0 Answers0