Aistis Taraskevicius
Aistis Taraskevicius

Reputation: 811

How to use templated struct in class c++

I am trying to use templated struct within a class, but cant figure out how to declare it properly

template<typename var>
struct Node
{
    var value;
    Node* left;
    Node* right;
};

class Tree
{
public:
    Tree();
    ~Tree();
    template<typename var>
    void insert(var key, Node *node);
    template<typename var>
    Node* search(var key, Node *node);
    void deleteTree(Node *node);
    void inOrderTraversePrint(Node* node);
    void preOrderTraversePrint(Node* node);
    void postOrderTraversePrint(Node* node);
    Node* getRoot();
    void resetRoot();
private:

    Node* root;
};

I keep getting couple errors " Node is not a type" and "Invalid use of template-name Node without an argument list".

I know how to template single class and methods within or outside the class, but this is first time I am using struct and trying to use templated struct within a class. What is proper way to declare and use templated struct within a class.

Upvotes: 2

Views: 30175

Answers (3)

Keegan Fisher
Keegan Fisher

Reputation: 360

Just change the Node declarations to Node<TypeName>, the compiler is complaining that Node is not a type, and it isn't, but Node<var> is a class in this case.

Upvotes: -1

utnapistim
utnapistim

Reputation: 27385

If Node uses var type internally, then it should be templated by it as well:

template<typename var>
struct Node
{
    var value;
    Node* left;
    Node* right;
};

template<typename T>
class Tree
{
public:
    Tree();
    ~Tree();

    void insert(T key, Node<T> *node);
    Node<T>* search(T key, Node<T> *node);
    void deleteTree(Node<T> *node);
    void inOrderTraversePrint(Node<T>* node);
    void preOrderTraversePrint(Node<T>* node);
    void postOrderTraversePrint(Node<T>* node);
    Node<T>* getRoot();
    void resetRoot();
private:

    Node<T>* root;
};

Edit:

this is first time I am using struct and trying to use templated struct within a class. What is proper way to declare and use templated struct within a class.

You can get away with not templating Tree class, if your tree data always has the same type:

class Tree
{
public:
    Tree();
    ~Tree();
    void insert(var key, Node<int> *node);
    Node* search(var key, Node<int> *node);
    void deleteTree(Node<int> *node);
    void inOrderTraversePrint(Node<int>* node);
    void preOrderTraversePrint(Node<int>* node);
    void postOrderTraversePrint(Node<int>* node);
    Node<int>* getRoot();
    void resetRoot();
private:

    Node<int>* root;
};

Second Edit

Variant implementation for nodes:

class Node
{
    virtual std::string ToString() = 0; // convert value to string
    virtual ~Node() = default;
    Node *left, *right;
};

template<typename T>
class ValueNode: public Node
{
    T value_;
public:
    ValueNode(T value): Node{ nullptr, nullptr }, value_{ std::move(value) } {}

    std::string ToString() override;
    {
        std::ostringstream oss;
        oss << value_;
        return oss.str();
    }

    virtual ~ValueNode() = default;
};

class Tree
{
public:
    Tree();
    ~Tree();
    template<typename var>
    void insert(var key, Node *node)
    {
        // insert new ValueNode<var>{ key } here
    }

    template<typename var>
    Node* search(var key, Node *node);
    void deleteTree(Node *node);
    void inOrderTraversePrint(Node* node);
    void preOrderTraversePrint(Node* node);
    void postOrderTraversePrint(Node* node);
    Node* getRoot();
    void resetRoot();
private:

    Node* root;
};

The idea here is to identify all operations to apply to all node values in the same way (in my example code, that means "conversion of the value to a string") and (first) declare them as abstract operations in Node, then implement them depending on the value type (as virtual function implmentations in ValueNode).

This will allow you to make abstraction of the fact you have multiple types in the nodes, in the Tree class.

That said, if you use boost, you should probably use boost::variant or boost::any in place of typename var in Node, in your original code.

Upvotes: 6

GingerPlusPlus
GingerPlusPlus

Reputation: 5636

"Node is not a type" and "Invalid use of template-name Node without an argument list"

Compiler says you exactly what is wrong. Node is indeed not a type. Node is a template.

The types are for example Node<int>, Node<std::string>, Node<T> (inside Tree) and Node<var> (inside Node).

Upvotes: 2

Related Questions