I have 4 files node.hpp, node.cpp, linked_list.hpp and linked_list.cpp. There codes are respectively below.
#ifndef NODE
#define NODE
template <typename T>
struct Node {
T data;
Node<T>* next;
Node(const T& data);
Node(const T& data, const Node<T>* next);
};
#endif // NODE
#include "node.hpp"
template <typename T>
Node<T>::Node(const T& data) : data(data), next(nullptr) {}
template <typename T>
Node<T>::Node(const T& data, const Node<T>* next) : data(data), next(next) {}
#ifndef LINKED_LIST
#define LINKED_LIST
#include <cstddef>
#include "node.hpp"
template <typename T>
class LinkedList {
public:
LinkedList();
LinkedList(const T& data);
LinkedList(const LinkedList& other);
~LinkedList();
void push_front(const T& data);
void push_back(const T& data);
void pop_front();
void pop_back();
T front() const;
T back() const;
T get(const int& index) const;
void set(const int& index, const T& data);
void insert(const size_t& index, const T& data);
void remove(const size_t& index);
int getSize() const;
bool isEmpty() const;
void clear();
void print() const;
LinkedList& operator=(const LinkedList& other);
bool operator==(const LinkedList& other) const;
bool operator!=(const LinkedList& other) const;
T operator[](const size_t& index) const;
T& operator[](const size_t& index);
private:
Node<T>* head;
size_t size = 0;
};
#endif // LINKED_LIST
#include "linked_list.hpp"
#include <iostream>
template <typename T>
LinkedList<T>::LinkedList() : head(nullptr), size(0) {}
template <typename T>
LinkedList<T>::LinkedList(const T& data) : head(new Node<T>(data)), size(1) {}
template <typename T>
LinkedList<T>::LinkedList(const LinkedList& other) {
this->head = nullptr;
this->size = 0;
Node<T>* current = other.head;
while (current != nullptr) {
this->push_back(current->data);
current = current->next;
size++;
}
}
template <typename T>
LinkedList<T>::~LinkedList() {
this->clear();
}
template <typename T>
LinkedList<T>& LinkedList<T>::operator=(const LinkedList& other) {
if (this == &other) return *this;
this->clear();
Node<T>* current = other.head;
while (current != nullptr) {
this->push_back(current->data);
current = current->next;
}
return *this;
}
template <typename T>
bool LinkedList<T>::operator==(const LinkedList& other) const {
if (size != other.size) return false;
Node<T>* current1 = head;
Node<T>* current2 = other.head;
while (current1 != nullptr) {
if (current1->data != current2->data) return false;
current1 = current1->next;
current2 = current2->next;
}
return true;
}
template <typename T>
bool LinkedList<T>::operator!=(const LinkedList& other) const {
return !(*this == other);
}
template <typename T>
void LinkedList<T>::push_front(const T& data) {
Node<T>* newNode = new Node<T>(data);
newNode->next = head;
head = newNode;
++size;
}
template <typename T>
void LinkedList<T>::push_back(const T& data) {
if (head == nullptr)
head = new Node<T>(data);
else {
Node<T>* current = head;
while (current->next != nullptr) current = current->next;
current->next = new Node<T>(data);
}
++size;
}
template <typename T>
void LinkedList<T>::pop_front() {
if (head == nullptr) return;
Node<T>* temp = head;
head = head->next;
delete temp;
--size;
}
template <typename T>
void LinkedList<T>::pop_back() {
if (this->head == nullptr) return;
if (this->head->next == nullptr) {
delete this->head;
this->head = nullptr;
} else {
Node<T>* current = this->head;
while (current->next->next != nullptr) current = current->next;
delete current->next;
current->next = nullptr;
}
--size;
}
template <typename T>
T LinkedList<T>::front() const {
return this->head->data;
}
template <typename T>
T LinkedList<T>::back() const {
Node<T>* current = this->head;
while (current->next != nullptr) current = current->next;
return current->data;
}
template <typename T>
T LinkedList<T>::get(const int& index) const {
if (index < 0 || index >= size) return T();
Node<T>* current = this->head;
for (int i = 0; i < index; ++i) current = current->next;
return current->data;
}
template <typename T>
void LinkedList<T>::set(const int& index, const T& data) {
if (index < 0 || index >= size) return;
Node<T>* current = this->head;
for (int i = 0; i < index; ++i) current = current->next;
current->data = data;
}
template <typename T>
void LinkedList<T>::insert(const size_t& index, const T& data) {
if (index < 0 || index > size) return;
if (index == 0)
push_front(data);
else {
Node<T>* current = this->head;
for (size_t i = 0; i < index - 1; ++i) current = current->next;
Node<T>* newNode = new Node<T>(data);
newNode->next = current->next;
current->next = newNode;
++size;
}
}
template <typename T>
void LinkedList<T>::remove(const size_t& index) {
if (index < 0 || index >= size) return;
if (index == 0)
pop_front();
else {
Node<T>* current = this->head;
for (size_t i = 0; i + 1 < index; ++i) current = current->next;
Node<T>* temp = current->next;
current->next = current->next->next;
delete temp;
--size;
}
}
template <typename T>
int LinkedList<T>::getSize() const {
return size;
}
template <typename T>
bool LinkedList<T>::isEmpty() const {
return size == 0;
}
template <typename T>
void LinkedList<T>::clear() {
while (this->head != nullptr) pop_front();
}
template <typename T>
void LinkedList<T>::print() const {
Node<T>* current = this->head;
while (current != nullptr) {
std::cout << current->data << " ";
current = current->next;
}
std::cout << std::endl;
}
template <typename T>
T LinkedList<T>::operator[](const size_t& index) const {
return get(index);
}
template <typename T>
T& LinkedList<T>::operator[](const size_t& index) {
if (index < 0 || index >= size) return T();
Node<T>* current = this->head;
for (int i = 0; i < index; ++i) current = current->next;
return current->data;
}
int main() {
LinkedList<int> list;
list.push_back(1);
list.push_back(2);
list.push_back(3);
list.push_back(4);
list.print();
list.remove(2);
list.print();
return 0;
}
makefile
is,
linked_list:
g++ linked_list.cpp node.cpp -Wall -o linked_list
./linked_list
rm ./linked_list
The compiler gives following errors,
make linked_list
g++ linked_list.cpp node.cpp -Wall -o linked_list
/usr/bin/ld: /tmp/ccV1cNdz.o: in function `LinkedList<int>::push_back(int const&)':
/media/meesumaliqazalbash/Personal/Data-Structures/cpp/linked_list.cpp:74: undefined reference to `Node<int>::Node(int const&)'
/usr/bin/ld: /media/meesumaliqazalbash/Personal/Data-Structures/cpp/linked_list.cpp:78: undefined reference to `Node<int>::Node(int const&)'
collect2: error: ld returned 1 exit status
make: *** [makefile:17: linked_list] Error 1
I have tried altering the command and there is no success.
linked_list:
g++ -c node.cpp -Wall -o node.o
g++ -c linked_list.cpp -Wall -o linked_list.o
g++ node.o linked_list.o -Wall -O -o linked_list -g
./linked_list
rm ./linked_list
Error
make linked_list
g++ -c node.cpp -Wall -o node.o
g++ -c linked_list.cpp -Wall -o linked_list.o
g++ node.o linked_list.o -Wall -O -o linked_list -g
/usr/bin/ld: linked_list.o: in function `LinkedList<int>::push_back(int const&)':
linked_list.cpp:(.text._ZN10LinkedListIiE9push_backERKi[_ZN10LinkedListIiE9push_backERKi]+0x3b): undefined reference to `Node<int>::Node(int const&)'
/usr/bin/ld: linked_list.cpp:(.text._ZN10LinkedListIiE9push_backERKi[_ZN10LinkedListIiE9push_backERKi]+0x86): undefined reference to `Node<int>::Node(int const&)'
collect2: error: ld returned 1 exit status
make: *** [makefile:19: linked_list] Error 1
I made a raytracer a month ago and there I was linking multiple files and it shows no problem. I guess there maybe some issue with my VSCode settings.
This is task.json
.
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++ build active file",
"command": "/usr/bin/g++",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": ["$gcc"],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Task generated by Debugger."
}
],
"version": "2.0.0"
}
This is settings.json
.
{
"files.associations": {
"array": "cpp",
"atomic": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"compare": "cpp",
"list": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"algorithm": "cpp",
"chrono": "cpp",
"functional": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"cmath": "cpp",
"fstream": "cpp",
"future": "cpp",
"iomanip": "cpp",
"istream": "cpp",
"limits": "cpp",
"numeric": "cpp",
"ostream": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"string_view": "cpp",
"thread": "cpp",
"utility": "cpp",
"typeinfo": "cpp",
"valarray": "cpp",
"variant": "cpp",
"*.inc": "cpp",
"iostream": "cpp",
"bitset": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"codecvt": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"map": "cpp",
"set": "cpp",
"unordered_set": "cpp",
"exception": "cpp",
"iterator": "cpp",
"source_location": "cpp",
"initializer_list": "cpp",
"iosfwd": "cpp",
"mutex": "cpp",
"new": "cpp",
"numbers": "cpp",
"semaphore": "cpp",
"cinttypes": "cpp"
}
}