Well, I've checked for missing semicolons, and to my knowledge I don't have any inclusion loops, so I'm kind of stumped. I've been looking at other examples posted and I still don't quite see what I'm missing. I'm going to guess it's something to do with the use of templates that I'm not dealing with right, but I really don't know.
In file included from customtester.cpp:6:0:
MyBSTree.h:23:1: error: expected class-name before â{â token
File:
#ifndef MYBSTREE_H
#define MYBSTREE_H
template <typename T> //not sure which of these I need,
class AbstractBSTree; //the include, the forward
#include "abstractbstree.h" //declaration, or both.
template <typename T>
class TreeNode
{
T m_data;
TreeNode<T> * m_right;
TreeNode<T> * m_left;
};
template <typename T>
class MyBSTree:public AbstractBSTree //this would be line 23
{
TreeNode<T> * m_root;
int m_size;
};
#endif
Anything I'm missing? I cannot modify "abstractbstree.h"
try:
public AbstractBSTree<T>
the compiler will assume the <T> only inside a template body and only for the templated class, not in public space
You're missing a <T>.
Since AbstractBSTree is a template class, you need to specify the template parameter when you derive from it for MyBSTree:
template <typename T>
class MyBSTree:public AbstractBSTree<T> // <-- Use <T> here
{
TreeNode<T> * m_root;
int m_size;
};
Related
I implemented BinaryTree class and inside the definition of BinaryTree I defined the structure "BinaryNode".
#ifndef BINARYTREE_H
#define BINARYTREE_H
#include <iostream>
#define SPACE 10
template <class T,class U>
class BinaryTree
{
protected:
typedef struct BinaryNode{
U data;
T key;
struct BinaryNode* left;
struct BinaryNode* right;
struct BinaryNode* parent;
BinaryNode(const T _key, const U& _data): key(_key), data(_data){}
virtual ~BinaryNode(){
if(left)
delete left;
if(right)
delete right;
}
}BinaryNode;
BinaryNode* root;
Now, I want to implement another sort of BinaryTree, which is a Heap. So I want to inherit from BinaryTree and add one field, this field is a pointer of type BinaryNode, which points the last leaf in the heap (heaps are complete trees, so that if the last level is not full, the last leaf is the leaf in the right tip).
#ifndef HEAP_H
#define HEAP_H
#include "BinaryTree.h"
template <class T,class U>
class Heap : public BinaryTree<T,U>
{
public:
//|--------------------- Constructors ----------------------|
Heap() : lastLeaf(NULL) {}
//|-------------------- Private fields ---------------------|
private:
BinaryNode* lastLeaf;
When I try to compile I get this error:
error: 'BinaryNode' does not name a type; did you mean 'BinaryTree'?|
Now if I try instead:
struct BinaryNode* lastLeaf;
In addition, everywhere I use BinaryNode* in the program, I get the error:
error: 'BinaryNode' has not been declared
So its not just in the field definition.
What can I do?
You derived class doesn't know what template parameters to apply to BinaryNode. Therefore, you need:
template <class T,class U>
class Heap : public BinaryTree<T,U>
{
// ...
typename BinaryTree<T,U>::BinaryNode* lastLeaf;
};
Live demo
As per #AdrianMole's comment, clang needs the typename keyword here, so I have added that to my answer. And you don't need to use typedef, please see updated demo.
Adding this line:
typedef struct BinaryTree<T,U>::BinaryNode BinaryNode;
to the beggining of the file solved it.
1.I did something as below:
template <class T>
class RBTree{
public:
struct TreeNode{
T data;
bool color;
TreeNode* left;
TreeNode* right;
TreeNode* parent;
static TreeNode* NIL;
TreeNode(T data, TreeNode* parent, TreeNode* left = NIL, TreeNode* right = NIL)
:data(data), color(RED), left(left), right(right), parent(parent){}
}
TreeNode* TreeNode::NIL = new TreeNode(-1, nullptr);
};
And it throws me an error...
[Error] invalid use of qualified-name 'RBTree<T, Comp>::TreeNode::NIL'
I really don't know why... after I made it outside of the whole class RBTree, as blow, it works...
template <class T>
class RBTree{
...
};
template <class T>
typename RBTree<T>::TreeNode* RBTree<T>::TreeNode::NIL = new TreeNode(-1, nullptr);
But I don't know why I got an error at the first time?
I think the grammar may be correct...
2.Soon I made my class as below.
//in RBTree.hpp
template <class T>
class RBTree{
public:
... //the same as above
private:
TreeNode* root;
};
template <class T>
typename RBTree<T>::TreeNode* RBTree<T>::TreeNode::NIL = new TreeNode(-1, nullptr);
//in RBTree_IMPL.hpp
template <class T>
void RBTree<T>::insert(const T & data){
if(root == nullptr){
root = new TreeNode(data, nullptr);
...
}
...
}
//in RBTree_test.cpp
int main(){
RBTree<int> rb;
rb.insert(3);
}
I got lots of errors like
[Error] recursive evaluation of default argument for 'RBTree<T>::TreeNode::TreeNode(T, RBTree<T>::TreeNode*, RBTree<T>::TreeNode*, RBTree<T>::TreeNode*) [with T = int]'
maybe about the constructor of the inner class TreeNode. The error happens when I use the RBTree::insert() in main() to create the 'root' node.
I don't know why. It maybe very interesting to probe the static member. And thank you for reading my question. Due to the fact that in 90 mins can only ask one question, so I write two questions in it.. Thx!
static data members must be defined at namespace scope. You were attempting to define it at class scope.
As for the second error, you have an infinite recursion. You are trying to define what the value of NIL is, but since you aren't providing all the arguments, the default arguments are being used, which means you are effectively declaring
template <class T>
typename RBTree<T>::TreeNode* RBTree<T>::TreeNode::NIL =
new TreeNode(-1, nullptr,NIL,NIL);
Maybe you intended for the default arguments to be nullptr instead.
This question already has an answer here:
Nested templates with dependent scope
(1 answer)
Closed 6 years ago.
having trouble when trying to compile a template class.
In the .h file
template <typename dataType>
class Node {
private:
dataType nodeData;
Node<dataType>* nextLink;
Node<dataType>* previousLink;
public:
Node(const dataType& nodeData);
// methods
In the .template file
template <typename dataType>
Node<dataType>::dataType Node<dataType>::getData() const {
return nodeData;
};
The error I get when trying to compile is:
need ‘typename’ before ‘Node<dataType>::dataType’ because ‘Node<dataType>’ is a dependent scope
Node<dataType>::dataType Node<dataType>::getData() const {
So then I add typename and it then gives me this error:
error: expected nested-name-specifier before ‘dataType’
typename dataType getData() const;
^
error: expected ‘;’ at end of member declaration
error: declaration of ‘int Node<dataType>::dataType’
error: shadows template parm ‘class dataType’
template <typename dataType>
^
What have I done wrong?
There is no member called dataType, I assume the return type should be just the template dataType:
template <typename dataType>
dataType Node<dataType>::getData() const {
return nodeData;
}
The compiler message is misleading in this case as it doesn't find proper definition, it assumes the dataType refers to the template argument.
template <typename DataType>
class Node {
public:
using dataType = DataType;
private:
dataType nodeData;
Node<dataType>* nextLink;
Node<dataType>* previousLink;
public:
Node(const dataType& nodeData);
dataType getData() const;
};
template <typename DataType>
typename Node<DataType>::dataType Node<DataType>::getData() const {
return nodeData;
};
specfy typename like this.
http://melpon.org/wandbox/permlink/Agu2s6vw6OLfbbRh
The presented example code is incomplete, so one would have to guess at the concrete problem.
However, here's how to do that class in a practical way, without problems like the one you're encountering:
template< class Item >
struct Node
{
Node* next;
Node* prev;
Item item;
};
Showing that it's sometimes possible to solve a problem without knowing the exact details.
I am trying to use templates for a nested class. I am not sure how to access the class type of the inner class from another class.
Sample Code below.
// I have a List class that can accept any type. It has an inner class
template <class T>
class List
{
public:
class Node
{
public:
T data;
Node* next;
Node* prev;
};
void addElement(Node& value);
private:
Node* head;
};
// Here I am making an array of Lists
template <class T>
class ListArray
{
public:
// Here is my question.
void add(Node& value); // How to give "Node" class type here ?
private:
List<T> _listArr[10];
};
// Is the below the right way to define ListArray::add, especially the way in which Node type can be passed to it ?
template <class T>
void ListArray<T>::add(List<T>::Node& value)
{
// Make a call to List::addElement and pass Node& value
_listArr[0].addElement(value);
//....
}
Could you kindly let me know how the above can be achieved ? Thanks.
Node is a nested type of a class template:
template <class T>
class ListArray
{
public:
typedef typename List<T>::Node Node_type;
void add(Node_type& value); // Refer to it as Node_type
private:
List<T> _listArr[10];
};
And:
template <class T>
void ListArray<T>::add(typename ListArray<T>::Node_type& value)
{
_listArr[0].addElement(value);
//....
}
I used typedef to define local name for node type. It is very useful - now, clients of ListArray can write code, that uses Node_type explicitly (without knowing what it actually is). This technique is used heavily in std library - usually, std:: types have tons of typedefs to allow writing flexible code.
Also, note the typename keyword - it is required in case of nested types of class templates. It indicates, that given name is the name of a type (without it, you should get a compiler error).
what's the most effective way to template a class that calls will need to call a templated struct. This is the classic ordered list problem with templating. My entire ordered list works as of now (when I simply change the types manually). However, I am not sure how to go about templating the pair of objects (the struct and the class).
So basically, here is how my code is structured:
struct Node {
int* data;
Node* next;
};
class OList {
private:
Node* start;
int size;
public:
a bunch of manipulation functions
};
So, my desire is to simply template the struct, and then accept a parameter that will pass the template into the Node struct type. However, my first attempt, which was to do:
template<class T>
before the Node struct and change all the ints* to T* failed miserably. What might be a better approach in anybody's experience? Can anybody point me in the right direction or give me some good references for template basics? All I can find are specific questions, which doesn't give me a good background to how templating works.
UPDATE: My code works very well at this point. The only thing I still do not understand is how to return pointers of the Node struct in functions. For example, in a function that might be,
template <class T>
List<T>::Node<T>* List<T>pos(int val); //trying to return a pointer to the node at a specified spot
I get the following error: "Non-templated 'Node' used as template. note: use OList::template Node' to indicate that it is a template (???) error: need 'typename' before 'OList::Node' because 'OList is a dependent scope" What is the most efficient way to clear up these errors? Code works perfectly when this one function is commented out.
template <typename T> // <----
struct Node {
T* data; // <----
Node* next;
};
template <typename T> // <----
class OList {
private:
Node<T>* start; // <----
int size;
public:
a bunch of manipulation functions
};
Alternatively...
template <typename T>
class OList {
private:
typedef ::Node<T> Node; // <---- just do it once
Node* start;
...or as suggested in BWG's comment, define Node directly in OList, so all the <T> aspect is implicit...
template <typename T>
class OList {
private:
struct Node { T* data; int size; }; // <----
Node* start;
Example of out-of-line member function definition:
template <typename T>
class OList
{
private:
struct Node { T* data; };
Node* f(Node*);
public:
};
template <typename T>
typename OList<T>::Node* OList<T>::f(typename OList<T>::Node* p) // see notes
{
Node* p2 = p; // can use Node as if inside class definition
return p2;
}
Note the ugly line...
typename OList<T>::Node* OList<T>::f(typename OList<T>::Node* p)
...where typename is needed to indicate that Node names a type inside QList<T> (so it can do a bit more to make sure the function might makes sense even before it's instantiated for any specific type 'T'), and we need to continually mention both that Node's inside QList's scope, and that the specific instantiation of QList in which it's to be found is based on the template parameter T. It all makes sense, but it's a bit pedantic.
As for how templates work in general, that's arguably "too broad" for answers on Stack Overflow, but FWIW perhaps the fastest way to jump-start some practical understanding of that (which will need some refinement afterwards), is by comparing them to macros. Consider:
#define NODE(T) \
struct Node ## T { \
T* data; \
Node ## T* next; \
};
With this, you can say NODE(int) or NODE(float) to generate Node_int and Node_float structures for those types. With templates, you don't (normally) need to define each specialisation separately - it's done implicitly when used ("parametric polymorphism")- so just start using them for variables ala Node<int> my_node_for_ints.
Do you mean something like:
template <typename T>
struct Node {
T data;
Node* next;
};
template <typename T>
class OList {
private:
Node<T> start;
int size;
public:
};
?