I think this is simply an issue of syntax. But no matter how I do this I keep getting compiler errors. I'm using a Node-based list class and can't figure out how to write the declaration header. Where do I place the forward List class declaration, etc? I just don't know how to set this up. Below is the entire declaration header:
#include <iostream>
using namespace std;
class List;
template <typename T>
class Node{
private:
Node(T, Node*);
T data;
Node* next;
friend class List<T>;
friend ostream& operator<<(ostream&, const List<T>&);
};
class List{
public:
List(int = 0);
List(const List&);
~List();
bool gotoBeginning();
bool gotoEnd();
bool gotoNext();
bool gotoPrior();
bool insertAfter(T);
bool insertBefore(T);
bool remove(T&);
bool replace(T);
bool getCursor(T&) const;
bool empty() const;
bool full() const;
bool clear();
List<T>& operator=(const List&);
friend ostream& operator<<(ostream&, const List<T>&);
bool operator==(const List&) const;
private:
Node* head;
Node* cursor;
};
Change it to
template <class T>
class List
and add the T type to the nodes declarations
Node<T>* head;
Node<T>* cursor;
Related
According to Why isn't argument deduction allowed in function return type?
When specifying a return type in a template class member function we have to be specific, for example: "the type std::vector isn't a type, std::vector<int> is."
So why do both of these examples compile? If I don't include the <T> in the first example, it shouldn't even be considered a type right?
template<typename T>
Queue<T>::Queue(const Queue& st) {}
template<typename T>
Queue<T>::Queue(const Queue<T>& st) {}
Given this template class
template<typename T>
class Queue {
private:
struct Node {
Node (T value) : value(value), next(nullptr) {}
Node (T value, Node* next) : value(value), next(next) {}
T value;
Node* next;
};
Node* head;
size_t sz;
void cleanList();
public:
Queue();
Queue(const Queue& st);
Queue& operator=(const Queue& st);
~Queue();
size_t size() const noexcept;
bool isEmpty() const noexcept;
T& front();
const Tt& front() const;
void enqueue(const T& elem);
void dequeue();
};
The reason these examples work is because of the injected class name. When you have
template<typename T>
some_type<T> some_type<T>::some_func(some_type)
the return type is not in scope of the class so you need to provide the template parameter. In the function parameter you are in the scope of the class and in the scope of the class some_type is injected as a name for some_type<T> so you don't need to use some_type<T>.
I'm making my first binary search tree. I have a BinarySearchTreeNode nested inside of BinarySearchTree. I'm trying to overload the << operator for BinarySearchTreeNode, but I can't figure out how to get it to compile.
{
template<class Type>
class BinarySearchTree
{
//Forward declare classes
public:
class BinarySearchTreeNode;
//Declare
public:
BinarySearchTree();
private:
BinarySearchTreeNode *head;
//Nested classes:
public:
class BinarySearchTreeNode
{
friend std::ostream& operator <<(std::ostream &outs, const BinarySearchTreeNode& node);
public:
BinarySearchTreeNode();
BinarySearchTreeNode(const Type &data);
BinarySearchTreeNode *getRight() const;
BinarySearchTreeNode *getLeft() const;
void insert(const Type &data);
const Type &getData() const;
std::string recursiveToString();
private:
Type data;
List<int> lineNumbers;
BinarySearchTreeNode *left;
BinarySearchTreeNode *right;
void addNode(Type data);
void setRight(Type data);
void setLeft(Type data);
};
};
}
template<class Type>
std::ostream& cs20a::operator <<(std::ostream &outs, const typename BinarySearchTree<Type>::BinarySearchTreeNode& node)
{
outs << node.getData();
return outs;
}
This won't compile because it says that there is no matching declaration in the namespace cs20a. I can't figure out how to get it to compile. The only way I can get it to work is if I put the function definition at the top instead of declaring it at the top. My professor wants them all separate if possible.
Thank you
You could just add a declaration at the last of the namespace defination:
// ... ...
};
};
template<class Type>
std::ostream& operator <<(std::ostream &outs, const typename BinarySearchTree<Type>::BinarySearchTreeNode& node);
}
template<class Type>
std::ostream& cs20a::operator <<(std::ostream &outs, const typename BinarySearchTree<Type>::BinarySearchTreeNode& node)
{
outs << node.getData();
return outs;
}
Here's a skeletal program that builds successfully for me, using g++ 4.8.4.
I have added comments in the code to explain what I have done.
#include <iostream>
using namespace std;
namespace cs20a
{
// Declare the class template.
template <class Type> class BinarySearchTree;
// Declare the operator<<() function.
template <typename T> std::ostream& operator<<(std::ostream &outs,
const typename BinarySearchTree<T>::BinarySearchTreeNode& node);
template<class Type> class BinarySearchTree
{
public:
BinarySearchTree();
class BinarySearchTreeNode
{
// Make operator<<() a friend.
// This syntax makes sure that operator<< <int> is a friend of
// BinarySearchTree<int>::BinarySearchTreeNode but not a friend
// of BinarySearchTreeNode<double>::BinarySearchTreeNode.
friend std::ostream& operator<< <Type>(std::ostream &outs, const BinarySearchTreeNode& node);
public:
const Type &getData() const;
};
private:
BinarySearchTreeNode *head;
};
}
// Implement the function.
template<class Type>
std::ostream& cs20a::operator<<(std::ostream &outs,
const typename BinarySearchTree<Type>::BinarySearchTreeNode& node)
{
outs << node.getData();
return outs;
}
int main()
{
return 0;
}
So I'm working with templates and I've run into a problem. After I converted my code into templates I am no longer able to access the private members of my classes. I get the error that 'current' is a private member of 'Iterator'. So first I have each class:
template <class T>
struct nodeType {
T info;
nodeType<T> *link;
};
template <class T>
class Iterator {
public:
Iterator();
Iterator(nodeType<T> *);
T operator*();
bool IsNull();
Iterator<T> operator++();
Iterator<T> operator++(int);
bool operator==(const Iterator<T> &) const;
bool operator!=(const Iterator<T> &) const;
Iterator<T> &operator=(T);
private:
nodeType<T> *current;
};
template <class T>
class LinkedList {
public:
LinkedList();
LinkedList(const LinkedList<T> &);
~LinkedList();
void InsertHead(T);
Iterator<T> InsertAfter(T, Iterator<T>);
Iterator<T> Search(T);
bool IsEmpty();
void Print();
void DestroyList();
Iterator<T> Start();
Iterator<T> End();
const LinkedList<T> &operator=(const LinkedList<T> &);
private:
nodeType<T> *head;
};
Before I used templates I used the following code, but not current is private and this no longer works.
template <class T>
Iterator<T> LinkedList<T>::InsertAfter(T input, Iterator<T> marker) {
Iterator<T> newNode = new nodeType<T>;
Iterator<T> findNode = marker;
newNode = input;
newNode.current->link = findNode.current->link;
findNode.current->link = newNode.current;
return findNode;
}
Then I tried to do the following and It get no errors but when I called the InsertAfter function to add a new item to the list it doesn't show up. I did a cout newNode = input; and it shows the value I want to insert, but the nodes don;t seem to connect up. Why can't I use the previous code I was doing before? Like newNode.current->link = findNode.current->link;
template <class T>
Iterator<T> Iterator<T>::operator++() {
current = current->link;
return *this;
}
template <class T>
Iterator<T> Iterator<T>::operator++(int) {
Iterator<T> temp;
temp = *this;
++(*this);
return temp;
}
template <class T>
Iterator<T> LinkedList<T>::InsertAfter(T input, Iterator<T> marker) {
Iterator<T> newNode = new nodeType<T>;
Iterator<T> findNode = marker;
newNode = input;
newNode++ = findNode++;
findNode++ = newNode;
return findNode;
}
You can't do newNode.current within a member function of LinkedList, because current is private to Iterator. That's what private means - it is only accessible from member functions of the class it belongs in.
Clearly your "old" code was different. Possibly you had Iterator friend LinkedList in the old code. If you post your old code it might clear things up.
I have the following code:
template <class T>
class List {
public:
class Iterator;
class ConstIterator;
//Constructors and Destructors.
List() : head(NULL), tail(NULL), size(0) {}
List(const List& list);
~List();
//Methods
Iterator begin();
Iterator end();
void insert(const T& data);
void insert(const T& data, const Iterator& iterator);
void remove(const Iterator& iterator);
int getSize() const;
Iterator find();
void sort();
//Operators
List operator = (const List& list);
private:
class Node;
Node* head;
Node* tail;
int size;
};
template <class T>
class List<T>::Node
{
public:
//Constructors and destructors
Node(const T& _data, const Node* _next) : data(_data), next(_next) {}
~Node(); //Destructor
//Methods
//Operators
Node operator = (const Node& node);
private:
T data;
Node* next;
};
template<class T>
class List<T>::Iterator
{
public:
Iterator() : list(NULL), node(NULL){} //Constructor
Iterator(const Iterator& it) : list(it.list), node(it.node) {}
~Iterator(); //Destructor
Iterator& operator=(const Iterator& it);
T& operator * ();
T& operator ++ ();
T operator ++ (int);
T& operator -- ();
T operator -- (int);
bool operator == (const Iterator& iterator) const;
bool operator != (const Iterator& iterator) const;
private:
List<T>* list;
Node* node;
};
template<class T>
class List<T>::ConstIterator
{
public:
ConstIterator() : list(NULL), node(NULL){}
ConstIterator(const ConstIterator& it) : list(it.list), node(it.node) {}
~ConstIterator(); //Destructor
ConstIterator& operator=(const ConstIterator& it);
T& operator * ();
T& operator ++ ();
T operator ++ (int);
T& operator -- ();
T operator -- (int);
bool operator == (const ConstIterator& iterator) const;
bool operator != (const ConstIterator& iterator) const;
private:
const List<T>* list;
const Node* node;
};
template<class T>
Iterator List<T>::begin() {
return Iterator(this, head);
}
When I try to compile I get the following error:
error: expected constructor, destructor, or type conversion before ‘List’
On line:
Iterator List<T>::begin() {
I'm not sure what I'm doing wrong.
Iterator is not defined, but List<T>::Iterator is. You will also need to add typename:
template<class T>
typename List<T>::Iterator List<T>::begin() { ... };
Here, typename is required as an ambiguitator to tell the compiler that List<T>::Iterator is a type (rather than a static member). This is always required in the templated context (see here).
if you write the body of the function outside the class declaration, it should be:
typename List<T>::Iterator List<T>::begin() { ... }
edit: typename added
so thats what i got going.
template<class T>
class List{
Node<T> head;
int size;
public:
class Iterator;
template <class T>
class List<T>::Iterator{
public:
Iterator& operator++();
i'm trying to implement like so:
template<class T>
typename List<T>::Iterator& List<T>::Iterator::operator++()
but it keeps telling me "Member declaration not found"
EDIT:
thats the entire relevent code:
template <class T>
class Node {
T data;
Node<T>* next;
public:
Node () : next(0){};
Node (const T& info, Node<T>* next = 0) : data(info), next(next){};
friend class List<T>;
friend class Iterator;
friend class ConstIterator;
};
template<class T>
class List{
Node<T> head;
int size;
void listSwap(Node<T>* node1, Node<T>* node2);
public:
class Iterator;
class ConstIterator;
List ();
List(const List<T>& list);
List& operator=(const List<T>& list);
ConstIterator begin() const;
Iterator begin();
ConstIterator end() const;
Iterator end();
void insert(const T& t);
void insert(const T& t,const Iterator& it);
void remove(const Iterator& it);
// template<class Function>
// ConstIterator find(Function f);
template<class Function>
Iterator find(Function f);
template<class Function>
void sort(Function f);
int getSize();
bool operator==(const List<T>& list2) const;
bool operator!=(const List<T>& list2) const;
~List();
};
template <class T>
class List<T>::Iterator{
List<T>* list;
Node<T>* index;
public:
Iterator(List<T> list);
Iterator(List<T> list, Iterator& it);
Iterator& operator++();
Iterator operator++(int);
T operator*();
bool operator==(const Iterator& iterator2);
bool operator!=(const Iterator& iterator2);
~Iterator();
friend class List<T>;
};
thought I think it is ok :/
so frustrating sometimes....
Thank you guys for the help!
You don't need template<class T> class List<T>::Iterator in the Iterator class definition if iterator is a nested class. Just class Iterator.
template<class T>
class List{
Node<T> head;
int size;
public:
class Iterator
{
public:
Iterator& operator++();
....
};
....
};
Either that, or you are missing the closing }; of your List class:
template<class T>
class List{
Node<T> head;
int size;
public:
class Iterator;
};
^^ HERE!
I see some obvious bugs, as the class List is not closed before you define List<T>::Iterator, but I presume it is so because you cut off some portion of your code.
Unfortunately, I was unable to reproduce your case. The following code:
class List {
int size;
public:
class Iterator;
};
template <class T>
class List<T>::Iterator {
public:
Iterator& operator++();
};
template <class T>
typename List<T>::Iterator& List<T>::Iterator::operator++() {
return *this;
}
int main() {
}
And it compiles just fine under g++ (4.6.3) and clang++ (3.1), so the problem is somewhere else which you are not showing us.
You first code sample seems to be shreeded beyond recognition.
As for your second (longer) section of code, I don't see anthing wrong with it aside from one suspect area. Your friend declarations inside Node will refer to some non-template Iterator and ConstIterator classes from global namespace. Meanwhile, Iterator and ConstIterator from List are templates that do not belong to global namespace. Were those friend declarations in Node supposed to refer to Iterator and ConstIterator from List or not?