Singly linked list - Segmentation fault - c++

First, sorry for the long code. I did my best to trim it as small as possible.
I'm getting segmentation fault when i want to add a new element (void SLList::pushBack(const Data &rDATA)) to my singly linked list (in SLList.hxx). The segmentation fault caused by 0xbaadf00d value.
........................................................................................................
IniFile.h
#include "Section.h"
class IniFile
{
public:
IniFile() :
void addSection();
private:
SLList<Section> mContent;
};
IniFile.cpp
#include "IniFile.h"
IniFile::IniFile() :
mContent() {}
void IniFile::addSection() // This is the only one method what i call
{
mContent.pushBack(Section());
}
Section.h
#include "Pair.hxx"
#include "SLList.hxx"
class Section
{
public:
Section();
private:
SLList<Pair<std::string, std::string>> mKeyValuePairs;
};
Section.cpp
#include "Section.h"
Section::Section() :
mKeyValuePairs() {}
SLList.hxx
template <typename Data>
class SLList
{
public:
class Node
{
public:
Node(const Data &rDATA, Node *const pNEXT = nullptr) :
mData(rDATA),
mNext(pNEXT) {}
Node(const Node &rRHS)
{
mData = rRHS.mData;
*mNext = *rRHS.mNext;
}
~Node()
{
delete mNext;
}
Node &operator=(const Node &rRHS)
{
if (&rRHS == this)
return *this;
mData = rRHS.mData;
*mNext = *rRHS.mNext;
return *this;
}
private:
void setNext(Node *const pNext)
{
mNext = pNext;
}
friend void SLList<Data>::pushBack(const Data &rDATA);
private:
Data mData;
Node *mNext;
};
SLList() :
mHead(nullptr),
mTail(nullptr) {}
SLList(const SLList &rRHS)
{
*mHead = *rRHS.mHead;
*mTail = *rRHS.mTail;
}
SLList &operator=(const SLList &rRHS)
{
if (&rRHS == this)
return *this;
*mHead = *rRHS.mHead;
*mTail = *rRHS.mTail;
return *this;
}
~SLList()
{
clear();
}
void clear()
{
delete mHead;
}
void pushBack(const Data &rDATA)
{
Node *pNode = new Node(rDATA, nullptr); // I get segmentation fault at this point
if (!mTail)
{
mHead = pNode;
mTail = pNode;
}
else
{
mTail->setNext(pNode);
mTail = pNode;
}
}
private:
Node *mHead;
Node *mTail;
};
Pair.hxx
template <typename T1, typename T2>
class Pair
{
public:
Pair(const T1 &rFIRST, const T2 &rSECOND) :
mFirst(rFIRST),
mSecond(rSECOND) {}
private:
T1 mFirst;
T2 mSecond;
};

SLList's copy constructor and assignment operator are wrong in terms of Node* pointer management.
Also, Node's destructor shouldn't destroy the next Node object in the list. Not only is a recursive destructor bad for long lists, but also think of in the future if you ever want to remove a single Node without clearing the whole list. Your clear() method should directly iterate the list deleting Node objects one at a time without using recursion.
Try something more like this:
#include <utility>
template <typename Data>
class SLList
{
public:
class Node
{
public:
Node(const Data &rDATA, Node *const pNEXT = nullptr)
: mData(rDATA), mNext(pNEXT)
{
}
Node(const Node &rSRC)
: mData(rSRC.mData), mNext(nullptr)
{
}
Node &operator=(const Node &rRHS)
{
if (&rRHS != this)
mData = rRHS.mData;
return *this;
}
private:
Data mData;
Node *mNext;
friend class SLList<Data>;
};
SLList()
: mHead(nullptr), mTail(nullptr)
{
}
SLList(const SLList &rSRC)
: mHead(nullptr), mTail(nullptr)
{
Node *pNode = rSRC.mHead;
while (pNode)
{
pushBack(pNode->mData);
pNode = pNode->mNext;
}
}
SLList &operator=(const SLList &rRHS)
{
if (&rRHS != this)
{
SLList temp(rRHS);
std::swap(mHead, temp.mHead);
std::swap(mTail, temp.mTail);
}
return *this;
}
~SLList()
{
clear();
}
void clear()
{
Node *pNode = mHead;
mHead = mTail = nullptr;
while (pNode)
{
Node *pNext = pNode->mNext;
delete pNode;
pNode = pNext;
}
}
void pushBack(const Data &rDATA)
{
Node *pNode = new Node(rDATA);
if (!mHead) mHead = pNode;
if (mTail) mTail->mNext = pNode;
mTail = pNode;
}
private:
Node *mHead;
Node *mTail;
};
With that said, what you really should do is use std::list (or std::forward_list) and std::pair instead. There is no benefit to "reinventing the wheel" at all:
#include "Section.h"
#include <list>
class IniFile
{
public:
void addSection();
private:
std::list<Section> mContent;
};
#include "IniFile.h"
void IniFile::addSection()
{
mContent.push_back(Section());
}
#include <pair>
#include <list>
#include <string>
class Section
{
private:
std::list<std::pair<std::string, std::string>> mKeyValuePairs;
};
#include <list>
template <typename Data>
class SLList
{
public:
void clear()
{
mList.clear();
}
void pushBack(const Data &rDATA)
{
mList.push_back(rDATA);
}
private:
std::list<Data> mList;
};

Related

How to properly use template class with an abstract pointer type

I created a List with a template Node class to hold different data types such as Node<int> but also more complex types such as Node<BaseEvent*>.
I also have an event container class to hold different event objects so it has a member argument
List<BaseEvent*> events;
where BaseEvent is an abstract class with derived classes that are not abstract.
In the event container I have a method called "add" (see below) that adds a new event to that events.
BaseEvent* eventClone = event.clone();
The clone returns a pointer to a new derived object such as:
new OpenEvent(*this);
Once it calls the list's insert method, it instantiates a new Node (see below), and in the Node constructor it assigns the value like so:
value(new T(new_value))
So basically it allocates a pointer memory (T=BaseEvent*).
I think I might be losing the eventClone pointer and have a memory leak.
The problem is that when I debugged it I saw that both: T* value; (aka BaseEvent** value) and BaseEvent* eventClone have the same address in memory.
I'm not sure if when I do delete value in the destructor of Node it will just free the pointer allocation to BaseEvent* or also the data that it holds.
Any insights are welcome!
Relevant code snippets
Node<T>
template <class T>
class Node
{
public:
Node(const T& new_value, Node* new_next = NULL, Node* new_prev = NULL);
~Node();
const T& getValue() const;
Node<T>* getNext() const;
Node<T>* getPrev() const;
void setNext(Node* node);
void setPrev(Node* node);
private:
T* value;
Node* next;
Node* prev;
};
template <class T>
Node<T>::Node(const T& new_value, Node* new_next, Node* new_prev) :
value(new T(new_value))
{
next = new_next;
prev = new_prev;
}
template <class T>
Node<T>::~Node()
{
delete value;
}
...
Linked list that uses Node<T>
template <class T>
class List
{
public:
List();
~List();
int getSize() const;
Node<T>* getFirst() const;
Node<T>* getNext(Node<T>& node) const;
Node<T>* getPrev(Node<T>& node) const;
void insertStart(const T& data);
void insertLast(const T& data);
void insertAfter(Node<T>& target, const T& data);
void insertBefore(Node<T>& target, const T& data);
void removeNode(Node<T>& node);
bool contains(const T data);
private:
Node<T>* head;
int size;
};
template <class T>
List<T>::List() : head(NULL), size(0)
{
}
template <class T>
List<T>::~List()
{
Node<T>* temp;
while (head)
{
temp = head;
head = head->getNext();
delete temp;
size--;
}
}
...
template <class T>
void List<T>::insertStart(const T& data) {
if (size == 0)
{
head = new Node<T>(data);
}
else
{
Node<T>* temp = new Node<T>(data, head);
head->setPrev(temp);
head = temp;
}
size++;
}
...
The event container class:
class EventContainer
{
public:
EventContainer() :
events(List<BaseEvent*>()) {}
~EventContainer() {}
virtual void add(const BaseEvent&);
class EventIterator
{
public:
EventIterator() :
current(NULL) {}
EventIterator(Node<BaseEvent*>& node) :
current(&node) {}
EventIterator(Node<BaseEvent*>* node) :
current(node) {}
~EventIterator() {}
EventIterator& operator=(const EventIterator& nodeIterator) {
current = nodeIterator.current;
return *this;
}
EventIterator& operator++() {
current = current->getNext();
return *this;
}
BaseEvent& operator*() const {
return *(current->getValue());
}
friend bool operator==(const EventIterator& iterator1, const EventIterator& iterator2) {
return iterator1.current == iterator2.current;
}
bool operator!=(const EventIterator& iterator) const {
return !(*this == iterator);
}
private:
Node<BaseEvent*>* current;
};
virtual EventIterator begin() const;
virtual EventIterator end() const;
private:
List<BaseEvent*> events;
};
The implementation of add method:
void EventContainer::add(const BaseEvent& event) {
BaseEvent* eventClone = event.clone();
if (events.getSize() == 0)
{
events.insertStart(eventClone);
return;
}
Node<BaseEvent*>* current = events.getFirst();
while (current != NULL)
{
if (*eventClone < *(current->getValue()))
{
events.insertBefore(*current, eventClone);
return;
}
current = current->getNext();
}
events.insertLast(eventClone);
}
EventContainer::EventIterator EventContainer::begin() const {
return events.getFirst();
}
EventContainer::EventIterator EventContainer::end() const {
return NULL;
}

Why do I get compile errors when I try to make this constructor generic?

So I have these three classes made
template <class dataType>
class listEntry
{
private:
dataType data;
public:
listEntry *next;
listEntry *prev;
dataType getData() { return this->data; }
listEntry();
listEntry(dataType data) { this->data = data; }
~listEntry() {};
};
template <class dataType>
class List
{
private:
dataType *head;
dataType *tail;
int count;
public:
dataType *getHead() { return this->head; }
dataType *getTail() { return this->tail; }
void addToTail(dataType *newEntry);
void addToHead(dataType *newEntry);
int getCount() { return count; }
void printListForward();
List();
List(const List<dataType> &li);
~List();
};
template <class dataType>
class Queue: public List<dataType>
{
public:
void enQueue(dataType *newEntry);
Queue():List<dataType>() { return; }
Queue(const List<dataType>& li):List<dataType>(li) { return; }
Queue(dataType data);
Queue(listEntry<dataType> le);
}
And one of my constructors for the Queue is this:
template <class dataType>
Queue<dataType>::Queue(dataType data)
{
enQueue(new listEntry<int>(data));
}
However, I want enQueue(new listEntry<int>(data)); to be enQueue(new listEntry<dataType>(data)); so that it is generic and can work with any data type. But when I change it to that, I get compile errors.
The enQueue definition looks like this:
template <class dataType>
void Queue<dataType>::enQueue(dataType *newEntry)
{
this->addToTail(newEntry);
}
How come writing dataType instead of int gets compile errors?
There are some design issues with your code:
The head and tail members of List need to be declared as listEntry<dataType>* instead of as dataType*.
addToTail(), addToHead() and enQueue() should all take dataType values instead of dataType* pointers.
addToTail() and addToHead() need to create a new listEntry<dataType> object internally.
Try something more like this instead:
template <class dataType>
class listEntry
{
private:
dataType data;
public:
listEntry *prev;
listEntry *next;
dataType getData() const { return data; }
listEntry(const dataType &data, listEntry *prev = NULL, listEntry *next = NULL);
};
template <class dataType>
class List
{
public:
typedef listEntry<dataType> entryType;
private:
entryType *head;
entryType *tail;
int count;
public:
entryType* getHead() { return head; }
const entryType* getHead() const { return head; }
entryType* getTail() { return tail; }
const entryType* getTail() const { return tail; }
void addToTail(const dataType &data);
void addToHead(const dataType &data);
int getCount() const { return count; }
void printListForward() const;
List();
List(const List &li);
~List();
List& operator=(const List &li);
};
template <class dataType>
class Queue : public List<dataType>
{
public:
typedef List<dataType> listType;
void enQueue(const dataType &data);
Queue() {}
Queue(const Queue &q) : listType(q) {}
Queue(const listType &li) : listType(li) {}
Queue(const dataType &data);
};
...
template<class dataType>
listEntry<dataType>::listEntry(const dataType &data, listEntry *prev, listEntry *next)
: data(data), prev(prev), next(next)
{
}
template<class dataType>
void List<dataType>::addToTail(const dataType &data)
{
entryType *newEntry = new entryType(data, tail);
if (!head) head = newEntry;
if (tail) tail->next = newEntry;
tail = newEntry;
++count;
}
template<class dataType>
void List<dataType>::addToHead(const dataType &data)
{
entryType *newEntry = new entryType(data, NULL, head);
if (!tail) tail = newEntry;
if (head) head->prev = newEntry;
head = newEntry;
++count;
}
template<class dataType>
void List<dataType>::printListForward() const
{
entryType *entry = head;
while (entry)
{
//...
entry = entry->next;
}
}
template<class dataType>
void List<dataType>::List()
: head(NULL), tail(NULL), count(0)
{
}
template<class dataType>
void List<dataType>::List(const List<dataType> &li)
: head(NULL), tail(NULL), count(0)
{
const entryType *entry = li.getHead();
while (entry)
{
addToTail(entry->getData());
entry = entry->next;
}
}
template<class dataType>
void List<dataType>::~List()
{
entryType *entry = head;
while (entry)
{
entryType *next = entry->next;
delete entry;
entry = next;
}
}
template<class dataType>
List<dataType>& List<dataType>::operator=(const List<dataType> &li)
{
if (&li != this)
{
List<dataType> temp(li);
std::swap(head, temp.head);
std::swap(tail, temp.tail);
std::swap(count, temp.count);
}
return *this;
}
template <class dataType>
Queue<dataType>::Queue(const dataType &data)
{
enQueue(data);
}
template <class dataType>
void Queue<dataType>::enQueue(const dataType &data)
{
addToTail(data);
}
Then you can do things like this:
Queue<int> q;
q.enQueue(12345);
q.enQueue(67890);
q.printListForward();

Creating an new instance of a C++ class, results a duplicate

I'm new to C++. I'm trying to implement a LinkedList, for which I created two classes Node and LinkedList.
I created some test functions. One to test the Node creation and another to test the isEmpty function from LinkedList. However, when I try to test them. What's created in 'testNode()ends up being in the same Node I create insideLinkedListashead`.
This may be trivial question, however as a newcomer to C++ this concept is still no clear to me. I'd like to know why it is referring to the same instance created previously.
#include <iostream>
#include <assert.h>
using namespace std;
class Node
{
private:
int data;
int next;
public:
int getData(){return data;}
void setData(int new_data) {data = new_data;}
int getNext(){return next;}
void setNext(int new_next) {next = new_next;}
};
class LinkedList
{
Node head;
Node head2;
public:
bool isEmpty()
{
if (head.getData() == 0) {return true;}
return false;
}
};
void testNode()
{
Node aNode;
aNode.setData(15);
aNode.setNext(23);
assert (aNode.getData() == 15);
assert (aNode.getNext() == 23);
}
void testEmptyLinkedList()
{
LinkedList ll;
assert (ll.isEmpty() == true);
}
Initialize your data.
int data = 0;
int next = 0;
Live On Coliru
#include <iostream>
#include <cassert>
using namespace std;
class Node {
private:
int data = 0;
int next = 0;
public:
int getData() { return data; }
void setData(int new_data) { data = new_data; }
int getNext() { return next; }
void setNext(int new_next) { next = new_next; }
};
class LinkedList {
Node head;
Node head2;
public:
bool isEmpty() {
if (head.getData() == 0) {
return true;
}
return false;
}
};
void testNode() {
Node aNode;
aNode.setData(15);
aNode.setNext(23);
assert(aNode.getData() == 15);
assert(aNode.getNext() == 23);
}
void testEmptyLinkedList() {
LinkedList ll;
assert(ll.isEmpty() == true);
}
int main() {
testEmptyLinkedList();
}
If your intention is to implement LinkList, each node of the list should contain the address of the next one.
So "next" shoud be declared as a pointer to a Node. Same for the first node of the list.
class Node {
private:
int data;
Node *next;
....
};
class LinkedList {
private:
Node *head;
...
};

Copy constructor with vector with custom class not working?

I am trying to implement Hashtable via LinkedList for collisions and I am having problem implementing copy constructor inside Hashtable (confused with the const-correctness stuff).
This is the error I am seeing:
void LinkedList<KVP<T>>::add(const KVP<T> &)' : cannot convert argument 1 from 'const int' to 'const KVP<T> &
Here is my code:
Hashtable:
#include <stdlib.h>
#include <string>
#include <vector>
#include "LinkedList.h"
#pragma once
template <typename T>
struct KVP
{
KVP() {}
KVP(const T &data, const std::string &key) : data(data), key(key) {}
const std::string key;
T data;
};
template <typename T>
class Hashtable
{
typedef KVP<T> kvp;
typedef LinkedList<kvp> list;
std::vector<list> table;
std::size_t size;
public:
Hashtable(int size) : size(size), table(size) {}
Hashtable(const Hashtable& other) : size(other.size)
{
table = other.table; //this causes problems
}
Hashtable& operator=(Hashtable other)
{
swap(*this, other);
return *this;
}
...
};
Linked List:
#include <stdlib.h>
#include <memory>
#pragma once
template <typename T>
class LinkedList;
template <typename TNode>
class LinkedListIterator
{
friend class LinkedList<typename TNode::value_type>;
TNode* p;
public:
LinkedListIterator(TNode* p) : p(p) {}
LinkedListIterator(const LinkedListIterator& other) : p(other.p) {}
LinkedListIterator& operator=(LinkedListIterator other) { std::swap(p, other.p); return *this; }
void operator++() { p = p->next; }
void operator++(int) { p = p->next; }
bool operator==(const LinkedListIterator& other) { return p == other.p; }
bool operator!=(const LinkedListIterator& other) { return !(p == other.p); }
const int& operator*() const { return p->data; }
LinkedListIterator<TNode> operator+(int i)
{
LinkedListIterator<TNode> iter = *this;
while (i-- > 0 && iter.p)
{
++iter;
}
return iter;
}
};
template <typename T>
class Node
{
friend class LinkedList<T>;
friend class LinkedListIterator<Node<T>>;
friend class LinkedListIterator<const Node<T>>;
Node() : next(nullptr) {}
Node(const T &data) : data(data), next(nullptr) {}
Node<T> *next;
T data;
public:
typedef T value_type;
};
template <typename T>
class LinkedList
{
typedef Node<T> node;
std::size_t size;
std::unique_ptr<node> head;
std::unique_ptr<node> tail;
void init()
{
size = 0;
head.reset(new node);
tail.reset(new node);
head->next = tail.get();
}
public:
typedef LinkedListIterator<node> iterator;
typedef LinkedListIterator<const node> const_iterator;
LinkedList() { init(); }
LinkedList(const LinkedList& other)
{
init();
const_iterator i = other.begin();
while (i != other.end())
{
add(*i);
i++;
}
head.reset(other.head.get());
tail.reset(other.tail.get());
}
LinkedList(LinkedList&& other)
{
size = other.size;
head = other.head;
tail = other.tail;
other.size = 0;
}
LinkedList& operator=(LinkedList other)
{
swap(*this, other);
return *this;
}
LinkedList& operator=(LinkedList&& other)
{
assert(this != &other);
while (head->next != tail)
remove(begin());
head = other.head;
tail = other.tail;
size = other.size;
other.size = 0;
return *this;
}
virtual ~LinkedList()
{
while (head->next != tail.get())
remove(begin());
}
friend void swap(LinkedList& first, LinkedList& second)
{
std::swap(first.size, second.size);
std::swap(first.head, second.head);
std::swap(first.tail, second.tail);
}
void add(const T &value)
{
node *first = new node(value);
first->next = head->next;
head->next = first;
size++;
}
void remove(iterator& removeIter)
{
node *last = head.get();
iterator i = begin();
while (i != removeIter)
{
last = i.p;
++i;
}
if (i != end())
{
last->next = i.p->next;
size--;
delete i.p;
}
}
const int getSize()
{
return size;
}
iterator begin()
{
return iterator(head->next);
}
const_iterator begin() const
{
return const_iterator(head->next);
}
iterator end()
{
return iterator(tail.get());
}
const_iterator end() const
{
return const_iterator(tail.get());
}
};
On its own LinkedList copy ctor seems to work, e.g. this compiles:
LinkedList<int> list;
LinkedList<int> list2;
list2 = list;
But this doesn't:
Hashtable<int> table1(50);
Hashtable<int> table2 = table1;
edit: Also if I define table with a pointer:
std::vector<list*> table;
it works, but I don't think this is best way.
Your LinkedListIterator<const Node<T>>::operator* returns const int&, rather than the value type of the LinkedList<T>. Your LinkedList<int> test passed because the template parameter happened to match the hard-coded return type of operator*.

How do we include a struct in a c++ implementation file?

So I am trying to create my own implementation file which contains instructions for a Queue. I decided to use a linked list to implement the Queue class, meaning that I need to use my own Node struct. Unfortunately, I am stuck and don't know how to properly include this within the file.
This is what I have so far:
#include <string>
#ifndef NODE
template <class DataType>
struct Node
{
DataType data;
Node *next;
};
#endif
template <class DataType>
class Queue
{
public:
Queue();
bool isEmpty() const;
void push(const DataType& parameter);
bool peek(DataType& parameter) const;
bool pop(DataType& parameter);
void makeEmpty();
private:
Node<DataType>* front;
Node<DataType>* end;
};
template <class DataType>
Queue<DataType>::Queue()
: front(0), end(0)
{
}
template <class DataType>
bool Queue<DataType>::isEmpty() const {return 0 == front;}
template <class DataType>
void Queue<DataType>::push(const DataType& parameter)
{
Node<DataType>* node = new Node<DataType>;
node->data = parameter;
node->next = 0;
if (end) end->next = node;
else front = node;
end = node;
}
template <class DataType>
bool Queue<DataType>::peek(DataType& parameter) const
{
if (0 == front) return false; // failed
parameter = front->data;
return true; // success
}
template <class DataType>
bool Queue<DataType>::pop(DataType& parameter)
{
if (0 == front) return false; // failed
parameter = front->data;
Node<DataType>* p = front->next;
delete front;
front = p;
if (front == 0) end = 0;
return true; // success
}
template <class DataType>
void Queue<DataType>::makeEmpty()
{
end = 0;
Node<DataType>* p;
while (front)
{
p = front->next;
delete front;
front = p;
}
}
I'm not sure if I am enclosing the struct by the #ifndef correctly (i'm not even sure if this is the route I should be taking :/), should I be doing something similar to this or should I be doing something else with the code for the struct?
You can just drop the #ifdef/#endif entirely
This is a class template and it may occur many times in several tranlation units, as long as all the occurrences are identical (One Definition Rule)
Alternative
Since Node<> is purely a private concern, I'd make it a nested struct.
Here's a little demo making this more 'modern C++' style.
Edit Thanks to #R.MartinhoFernandes for showing a few more improvements and for reviewing this.
#include <memory>
template <typename T>
struct Queue {
Queue() : front(), end(/*nullptr*/) {}
// Copy-And-Swap idiom
// see http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Copy-and-swap
// or http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom
void swap(Queue& q) noexcept {
using std::swap;
swap(q.front, front);
swap(q.end, end);
}
Queue(Queue const& q) : front(), end() {
for(auto it=q.front.get(); it; it=it->next.get())
push(it->data);
}
Queue& operator=(Queue q) {
std::swap(*this, q);
return *this;
}
// end Copy-and-swap
// prevent stack overflows in ~Node if the list grows large (say >1k elements)
~Queue() { clear(); }
bool isEmpty() const {
return !front;
}
void push(T const& data) {
Ptr node(new Node(data));
if (end)
end->next = std::move(node);
else
front = std::move(node);
end = node.get();
}
bool peek(T& data) const {
if(front) data = front->data;
return front.get();
}
bool pop(T& data) {
if(!front) return false;
data = front->data;
front = std::move(front->next);
if(!front) end = nullptr;
return true;
}
void clear() {
end = nullptr;
while(front) front = std::move(front->next);
}
private:
struct Node;
typedef std::unique_ptr<struct Node> Ptr;
struct Node {
Node(T data) : data(std::move(data)), next() {}
T data;
Ptr next;
};
Ptr front;
Node* end;
};
#include <iostream>
int main(int argc, const char *argv[]) {
Queue<int> test;
test.push(1);
test.push(2);
test.push(3);
test.push(5);
test.clear();
test.push(32028);
test.push(10842);
test.push(1839);
test.push(23493);
test.push(9857);
int x;
test.peek(x);
while(test.pop(x)) {
std::cout << x << '\n';
}
}
Note: Perhaps the code in push has been golfed a bit too far, but hey, it shows you how modern C++ requires much less handholding (even without std::make_unique).
Note how I think Clang correctly handles the following version (i.e. with implicit std::move):
void push(const DataType& parameter) {
end = ((end? end->next : front) = Ptr(new Node(parameter))).get();
}
I'm not quite sure why gcc rejects it.