How to use templated struct in class c++

24,833

Solution 1

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.

Solution 2

"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).

Share:
24,833
Aistis Taraskevicius
Author by

Aistis Taraskevicius

Updated on April 02, 2020

Comments

  • Aistis Taraskevicius
    Aistis Taraskevicius about 4 years

    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.

  • Aistis Taraskevicius
    Aistis Taraskevicius over 9 years
    Well tree doesnt store any data, node stores int, but I want it to be able to store other data types such as string
  • utnapistim
    utnapistim over 9 years
    @AistisTaraskevicius, I will edit my answer to show that as well.
  • Aistis Taraskevicius
    Aistis Taraskevicius over 9 years
    Cheers, I actually got it work after your first post with templated class, but could you explain in more detail what your second edit does, does it allows storing all types as a string?
  • utnapistim
    utnapistim over 9 years
    @AistisTaraskevicius, it allows interpretation of all values as strings. Consider this code: Node* n = new ValueNode<int>{ 20 }; When you call n->ToString(); you get a string representation of the node, without caring that the node contains an int (if it contained some other type, you would still get a string). This will allow you to treat all Node specializations the same, regarding on what type they are specialized on (and make client code easier and uniform).
  • Aistis Taraskevicius
    Aistis Taraskevicius over 9 years
    Cheers, sounds definitely useful.
  • Alexander Patrikalakis
    Alexander Patrikalakis about 7 years
    You should provide a code snippet of the solution to illustrate.