As an example code I've given here, I have the feeling the use of std::shared_ptr
is wrong and should be replaced using a std::unique_ptr
because there's no real shared ownership semantics, besides of temporary needs.
How could that code be refactored correctly, e.g. using std::unique_ptr
instead?
#include <memory>
#include <iostream>
template<typename T>
class LinkedList {
private:
template<typename U = T>
struct Node {
U data;
std::shared_ptr<Node<U>> next;
};
std::shared_ptr<Node<T>> head;
public:
Node<T> const* insert(int position, T data) {
if(position < 0) {
throw std::invalid_argument("Parameter 'position' must be greater or equal to 0.");
}
std::shared_ptr<Node<T>> node = head;
int i = 0;
for(;node && node->next && i < position; node = node->next, ++i);
if(i != position) { // position is a value beyond the list positions
throw std::out_of_range("Parameter 'position' is out of range of the linked list.");
}
std::shared_ptr<Node<T>> newNode = std::make_shared<Node<T>>();
newNode->data = data;
newNode->next = node ? node->next : nullptr;
if(node) {
node->next = newNode;
}
else {
head = newNode;
}
return newNode.get();
}
// Other linked list operations ...
};
int main() {
LinkedList<int> ll;
auto newNode = ll.insert(0,5);
std::cout << newNode->data << std::endl;
}
I thought the move constructor of std::unique_ptr
should cover all assignments of std::unique_ptr<Node<T>>
variables well, but obviously it doesn't out of the box.
See the working code to play with here please.
I well know this question is kind of borderline here, since I'm asking how to rewrite that code properly regarding the constraints I'm setting up.
Though I don't get in which direction I have to go with that, as all my attempts are failing so far. I think there must be an appropriate solution just using a std::unique_ptr
.