Reputation: 811
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
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
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
Reputation: 5636
"
Node
is not a type" and "Invalid use of template-nameNode
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