I have written this Node class:
template<class T>
struct Node{
Node() : content(), col(RED), parent(0), left(0), right(0) {}
Node(const Node& orig) : content(orig.content), col(orig.col), parent(orig.parent), left(orig.left), right(orig.right) {}
virtual ~Node() {}
Node<T>& operator= (const Node<T>& node);
template <class sT>
friend std::ostream& operator<<(std::ostream& out,const Node<sT>&node);
T content;
Color col;
Node<T> *parent,*left,*right;
};
Now i would create a Node object with within a Node with within a std::pair and I have written this:
Node<Node< pair<int,char> > > n1 (Node<pair<int,char> >( pair<int,char>(45,'a') ));
but the compiler shows me this error:
main.cpp:31:84: error: no matching function for call to ‘Node<std::pair<int, char> >::Node(std::pair<int, char>)’
Which is the exact syntax to get what I want?
You are missing a constructor: Node(const T& x);
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>.
Given that a class template called Queue with a nested class Node (not a class template):
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();
};
I can do this:
template<typename T>
void Queue<T>::enqueue(const T& elem) {
Node* temp = new Node(elem);
}
It compiles, but why does declaring a Node not need more information? (like Queue::Node)
After reading Templates and nested classes/structures, all 3 of these also works and compiles:
template<typename T>
void Queue<T>::enqueue(const T& elem) {
typename LLQueue<Object>::Node* temp1 = new Node(elem);
LLQueue<Object>::Node* temp2;
LLQueue::Node* temp3;
}
Why do all versions work? Which is preferred when using a nested class in a class template?
It compiles, but why does declaring a Node not need more information?
This is how unqualified name lookup happens in a member function scope. First the compiler checks the scope of the function, doesn't find anything, and then moves on to the class scope. In the class scope it sees Node, so name lookup succeeds and you get the Node type that is a member of the class.
Why do all versions work?
C++ lets you be as explicit as you want to be. Any name can be fully qualified and that is what you are doing. With typename LLQueue<Object>::Node, the typename isn't needed, but it doesn't hurt anything. Its like doing struct foo{}; struct foo f; the struct isn't needed but it is allowed by the grammar. The second line with LLQueue<Object>::Node is just a less explicit way and also allowed since typename isn't actually required. LLQueue::Node works because in a class template class_name is injected into the class scope and it is class_name<template_params>.
I'm trying to add a nested struct (Node) that takes the same template param 'T' passed into the baseclass (LinkedList).
When I try to template the outer LinkedList class, I get a "explicit specialization of non-template class LinkedList" error. If I don't add it, the private Nodes "head" and "tail" don't recognize 'T'
When I add the template to the Node class, I get a "Declaration of 'T' shadows template parameter" error. However, if I don't add it explicitly to the Node class, the 'T' is not recognized at all in the struct.
How do I declare template and pass it correctly from the LinkedList class to the nested, private Node struct correctly?
template<class T>
class LinkedList<T> {
private:
template<typename T>
struct Node {
T value;
Node<T>* next;
Node<T>* previous;
Node<T>(T value, Node<T>* next, Node<T>* previous)
:value(value),
next(next),
previous(previous){}
Node<T>& operator=(const Node<T>&) = delete;
};
Node<T>* head;
Node<T>* tail;
LinkedList& operator=(const LinkedList&) = delete;
public:
LinkedList<T>()
:head(nullptr),
tail(nullptr){}
~LinkedList<T>();
LinkedList& insertTail(T value);
};
Lose all the extraneous <T> madness and simply used the outer template parameter. It is perfectly legal to do so:
template<class T>
class LinkedList
{
private:
struct Node {
T value;
Node* next;
Node* previous;
Node(T value, Node* next, Node* previous)
: value(value), next(next), previous(previous)
{}
Node& operator=(const Node&) = delete;
};
Node* head;
Node* tail;
LinkedList& operator=(const LinkedList&) = delete;
public:
LinkedList()
: head(nullptr)
, tail(nullptr)
{}
~LinkedList();
LinkedList& insertTail(T value);
};
Related: My crystal ball tells me you should read this before implementing the rest of the functions that are only declared here.
Best of luck.
When declaring a primary template (i.e., not a specialization), don't add <T> after the name:
template<class T>
class LinkedList {
Node shouldn't be a template; for any particular T, a LinkedList<T> should only have one type of Nodes - those that hold T:
struct Node {
T value;
Node* next;
// ...
};
Finally, the <T> is implied when you write the template's name in its definition, so you don't need to explicitly specify it:
LinkedList()
:head(nullptr),
tail(nullptr){}
~LinkedList();
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;
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