Reputation: 1360
template <typename T>
class LinkedListNode {
public:
friend class LinkedList;
friend class LinkedListIterator;
LinkedListNode(const T p_data) : data(p_data), next(nullptr) {}
~LinkedListNode() {
std::cout << "~LinkedListNode()\n";
}
private:
T data;
LinkedListNode<T>* next;
};
template <typename T>
class LinkedList { /* Redefinition of 'LinkedList' as different kind of symbol */
...
}
I made own linked-list data structure, but an error message is appeared to LinkedList
class.
If I try to compile the code, another error is occured.
error: template argument required for ‘class LinkedList’
class LinkedListNode {
^
error: template placeholder type ‘LinkedListNode’ must be followed by a simple declarator-id
LinkedListNode* pre_remove;
^~~~~~~~~~~~~~
I've added template <typename T>
above LinkedList
class so I can't understand why these error messages come out.
int main() {
LinkedList li;
...
}
----------------------------------------------------
error: class template argument deduction failed:
LinkedList li;
^~
Full source code of Linked List
Upvotes: 1
Views: 862
Reputation: 20141
As already hinted by dorKKnight, class LinkedList
is actually a template. Hence, you have to use it as such – even in friend
declarations.
template <typename T>
class LinkedListNode {
friend class LinkedList<T>;
The other part of the story is that LinkedList
and LinkedListNode
have a circular dependency. To break this, a template forward declaration is needed.
// forward declaration
template <typename T>
class LinkedList;
A complete sample:
// forward declaration
template <typename T>
class LinkedList;
template <typename T>
class LinkedListNode {
friend class LinkedList<T>;
public:
const T value;
private:
LinkedListNode *pNext;
public:
LinkedListNode(const T value): value(value), pNext(nullptr) { }
~LinkedListNode() = default;
};
template <typename T>
class LinkedList {
LinkedListNode<T> *pFirst, *pLast;
public:
LinkedList(): pFirst(nullptr), pLast(nullptr) { }
void push(const T value)
{
if (!pFirst) pFirst = pLast = new LinkedListNode<T>(value);
else {
pLast->pNext = new LinkedListNode<T>(value);
pLast = pLast->pNext;
}
}
void print(const char *sep = " ")
{
std::cout << "{";
for (LinkedListNode<T> *pNode = pFirst; pNode; pNode = pNode->pNext) {
std::cout << sep << pNode->value;
}
std::cout << sep << "}";
}
};
int main()
{
LinkedList<int> list;
list.push(1); list.push(2); list.push(3);
list.print();
}
Output:
{ 1 2 3 }
A matter of design:
It is usual to embed the class for a single node into the template class for the list because the node class is a list detail which need not to be “seen” anywhere else.
Redesigning the above sample:
#include <iostream>
template <typename T>
class LinkedList {
private:
struct Node {
const T value;
Node *pNext;
Node(const T value): value(value), pNext(nullptr) { }
};
Node *pFirst, *pLast;
public:
LinkedList(): pFirst(nullptr), pLast(nullptr) { }
void push(const T value)
{
if (!pFirst) pFirst = pLast = new Node(value);
else {
pLast->pNext = new Node(value);
pLast = pLast->pNext;
}
}
void print(const char *sep = " ")
{
std::cout << "{";
for (Node *pNode = pFirst; pNode; pNode = pNode->pNext) {
std::cout << sep << pNode->value;
}
std::cout << sep << "}";
}
};
int main()
{
LinkedList<int> list;
list.push(1); list.push(2); list.push(3);
list.print();
}
Output:
{ 1 2 3 }
As a bonus, the forward issue has been vanished.
Upvotes: 1