1

Following codes are part of a Red Black Tree program which has to take item as a char or int, so I decided to use a template class, however I don't know how to extend it through the complete program and the compiler sends me thousand errors:

The code has German names, so if it makes it easier to understand, I will translate some of them:

baum = tree
knote = node
links = left
rechts = right
rot = red
doppel = double
mittlere = middle
eltern = parent
einfuegen = insert
rs = rb = red black

Knote.hpp

#pragma once

template <class T>
class Knote {
public:
    Knote(T data = 0);
    bool rot;
    T item;
    Knote *links;
    Knote *rechts;
    Knote *eltern;
};

Knote.cpp

#include "Knote.hpp"

Knote<int>::Knote(int data)
{
    this->item = data;

    eltern = nullptr;
    links = nullptr;
    rechts = nullptr;
    rot = true;
}

now how should I do it for the rest?

Baum.hpp

#pragma once

#include "Knote.hpp"

#include <vector>

class Baum
{
public:
    Baum();
    void einfuegen(int x);
    void ausgabe_levelorder();
    void ausgabe_inorder();
private:
    Knote<int>* head;
    void rs_einfuegen(Knote<int>* &knote, Knote<int>* &eltern, int x, bool sw);
    int rot(Knote<int>* &knote);
    void links_rotation(Knote<int> * &links_knote);
    void rechts_rotation(Knote<int> * &links_knote);
    void levelorder(Knote<int>* knote, std::vector<Knote<int>*> &knoteQueue, int niveau, std::vector<int> &niveauQueue);
    void sort_levelorder(std::vector<Knote<int>*> &knoteQueue, std::vector<int> &niveauQueue);
    void inorder(Knote<int>* knote);
};

Baum.cpp

#include "Baum.hpp"

#include <iostream>

using namespace std;

Baum::Baum()
{
    ...
}

// XXX
void Baum::einfuegen(int x)
{
    ...
}

// XXX
int Baum::rot(Knote<int>* &knote)
{
    ...
}

// XXX
void Baum::rs_einfuegen(Knote<int> *& knote, Knote<int> *&eltern, int x, bool sw)
{
    ...
}

// XXX
void Baum::links_rotation(Knote<int>* &links_knote)
{
    ...
}

// XXX
void Baum::rechts_rotation(Knote<int>* &rechts_knote)
{
    ...
}

// XXX
void Baum::ausgabe_levelorder()
{
    ...
}

// XXX
void Baum::levelorder(Knote<int>* knote, vector<Knote<int>*> &knoteQueue, int niveau, vector<int> &niveauQueue)
{
    ...
}

// XXX
void Baum::sort_levelorder(vector<Knote<int>*> &knoteQueue, vector<int> &niveauQueue)
{
    ...
}

// XXX
void Baum::ausgabe_inorder()
{
    inorder(head->rechts);
    cout << endl;
}

// XXX
void Baum::inorder(Knote<int>* knote)
{
    if (knote != nullptr)
    {
        inorder(knote->links);
        cout << knote->item << " ";
        inorder(knote->rechts);
    }
}
Bahador
  • 75
  • 1
  • 11
  • 4
    First, you should not be separating the template implementation from the declaration. Plenty of links on SO about this. For one: http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – PaulMcKenzie May 21 '15 at 18:02
  • @PaulMcKenzie: Unless someone with more authority than you says you have to hide all implementation details from the client :-( – AndyG May 21 '15 at 18:23

2 Answers2

2
  1. Don't need to use Knote<T> in the class. Just use Knote. Instead of

    Knote<T> *links;
    Knote<T> *rechts;
    Knote<T> *eltern;
    

    just use:

    Knote *links;
    Knote *rechts;
    Knote *eltern;
    
  2. When you use the class template, make sure you provide a template parameter.

    Knote* head;
    

    is not right. You need to use

    Knote<int>* head;
    

    or

    Knote<char>* head;
    

    You pick the type that is appropriate for Baum.

  3. Move the implementation of Knote to the .h file from the .cpp file. See Why can templates only be implemented in the header file?.

Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • I did what you said, but I get this: `error C2512: 'Knote' : no appropriate default constructor available` – Bahador May 21 '15 at 18:52
  • @user300725, that is suprising. You have a constructor `Knote(int data = 0);` that should work as the default constructor. – R Sahu May 21 '15 at 19:03
  • well, I changed it to `Knote(T data)` and then to `Knote(T data = 0)` the code got compiled sucessfully! However I get ASCII numbers of the charachters as output, and I need the characters themselves... – Bahador May 21 '15 at 19:09
  • how do i get rid of the ascii? – Bahador May 21 '15 at 19:25
  • @user300725, please post the function that you use to print the data. – R Sahu May 21 '15 at 19:26
  • @user300725, it helps a little bit. I am still puzzled. Are you saying that you expected to see `a b c d` in the output but you are seeing `97 98 99 100` instead? – R Sahu May 21 '15 at 20:26
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/78470/discussion-between-user300725-and-r-sahu). – Bahador May 21 '15 at 20:42
0

For Knote.h, your template <typename T> line should be template <class T>

Also, in your constructor for Knote, you can't assign an int (data) to a T variable (item). For the constructor, you should have T data, instead of int data, since you don't know what type data needs to be (because it's a template).

Templated classes also don't have a cpp file. The implementation has to go in the .h after the class declaration (unless forward declared). If you do want to separate your header and "implementation" code parts, keep the .h as normal, but make an .hpp file for your method implementations. In the .h after the class declaration, put #include "Knote.hpp".

For normal methods, the format goes like the following:

template <typename T>
void Knote<T>::myMethod(parameters)
{
    //normal method stuff
}

For friend methods that take the templated class as a parameter, such as an overloaded the insertion operator (<<), the format goes like this:

//in class declaration in .h
template <class T>
class Bob
{
    //variables here

    template <typename U>
    void myfunc(Bob<U> value);  //have to use a different template variable

}

//define as normal in the .hpp (or further down the file if no .hpp used)
Adam Evans
  • 2,072
  • 1
  • 20
  • 29
  • I want to keep to the separated form with .hpp headers... And I can assign an `int` type to a `char` type. If I don't use a template class at all and put `char` for `item` instead of `int`, I will have `char` output – Bahador May 21 '15 at 18:59
  • 1
    Regarding *your `template ` line should be `template `*, Both are valid. Some prefer to use `typename` while others prefer to use `class`. – R Sahu May 21 '15 at 19:06
  • @user300725 Yes, you can assign an `int` to a `char` via type promotion. But because item is of type T, which can be anything, even objects (although you aren't using it with them), the type promotion won't always work. – Adam Evans May 21 '15 at 19:09