如何在类c ++中使用模板化结构

时间:2014-11-13 11:23:42

标签: c++ templates struct

我正在尝试在类中使用模板化struct,但无法弄清楚如何正确声明它

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;
};

我一直在犯错误#34;节点不是一种类型&#34;和&#34;模板名称Node的使用无效,没有参数列表&#34;。

我知道如何模拟单个class以及类内外的方法,但这是我第一次使用struct并尝试在类中使用模板struct。 在类中声明和使用templated struct的正确方法是什么。

3 个答案:

答案 0 :(得分:5)

如果Node在内部使用var类型,那么它也应该由它模板化:

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;
};

修改

  

这是我第一次使用struct并尝试在类中使用模板化结构。什么是在类中声明和使用模板化结构的正确方法。

如果您的树数据总是具有相同的类型,则可以不使用模板化Tree类:

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;
};

第二次修改

节点的变体实现:

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;
};

这里的想法是以相同的方式识别要应用于所有节点值的所有操作(在我的示例代码中,这意味着“将值转换为字符串”)和(首先)将它们声明为{中的抽象操作{1}},然后根据值类型实现它们(作为Node中的虚函数实现)。

这将允许您在ValueNode类中对节点中有多种类型的事实进行抽象。

也就是说,如果您使用boost,则应该在原始代码中使用Treeboost::variant代替Node中的typename var。

答案 1 :(得分:2)

  

Node不是类型”和“使用没有参数列表的模板名称Node无效

编译器说你到底出了什么问题。 Node确实不是一种类型。 Node是一个模板。

类型包括Node<int>Node<std::string>Node<T>Tree}内部和Node<var>Node内部)。

答案 2 :(得分:-1)

只需将Node声明更改为Node<TypeName>,编译器就会抱怨Node不是一个类型,但它不是,但Node<var>是一个类这种情况。