I've implemented a double linked list using weak and smart pointers. The program is working but I have doubts about that const
in the getPrev
signature method. If I put const
a the end of the method signature it will cause a binding reference error
error: binding reference of type 'std::weak_ptr<Node<Integer> >&' to 'const std::weak_ptr<Node<Integer> >' discards qualifiers
return prev;
Wasn't the purpose of that const
to mark *this
as const
? The return type is non-const for my understanding.
Here is the code, main.cpp
:
#include <memory>
#include <iostream>
#include "DoubleLinkedList.h"
class Integer {
private:
int number;
public:
Integer(int number) : number(number) {}
int get() { return number; }
};
int main() {
DoubleLinkedList<Integer> list;
list.insert(Integer(1));
list.insert(Integer(2));
list.insert(Integer(3));
list.insert(Integer(4));
list.insert(Integer(5));
return 0;
}
DoubleLinkedList.h
#include <memory>
#include <vector>
#include <iostream>
template <typename T>
class Node {
private:
T data;
std::weak_ptr<Node> prev;
std::shared_ptr<Node> next;
public:
Node(): data(0) {}
Node(const T &object) : data(object) {};
T getData() const {
return data;
}
void setData(T data) {
Node::data = data;
}
std::weak_ptr<Node> &getPrev() const {
return prev;
}
void setPrev(const std::weak_ptr<Node> &prev) {
Node::prev = prev;
}
std::shared_ptr<Node> &getNext() {
return next;
}
void setNext(const std::shared_ptr<Node> &next) {
Node::next = next;
}
};
template <typename T>
class DoubleLinkedList {
private:
std::shared_ptr<Node<T>> header;
std::weak_ptr<Node<T>> trailer;
int size;
public:
DoubleLinkedList() : size(0) {}
void insert(const T &value) {
auto node = std::make_shared<Node<T>>(value);
if (size++ == 0) {
header = node;
} else {
auto last = trailer.lock();
last->getNext() = node;
node->getPrev() = last;
}
trailer = node;
}
};
If you are inside a const
method, all the data members are considered const
.
That is, inside this function:
std::weak_ptr<Node> &getPrev() const
you can imagine the member variables like this:
const T data;
const std::weak_ptr<Node> prev;
const std::shared_ptr<Node> next;
It should be clear that you cannot return a non-const reference to a const object:
const int x;
int& getX()
{
return x; // error
}
The reference would allow you to modify x
even though it is const
, so this is forbidden (formally: a non-const reference cannot bind to a const object).
Inside a const
member function of Node
, prev
is a const std::weak_ptr<Node>
, so a std::weak_ptr<Node>&
cannot bind to it for the exact same reason.
It appears that within insert
you do intend to modify node
(by changing its prev
value), in which case the getPrev
function should not be const (because you intend to modify the object). But this kind of access should probably be reserved for the DoubleLinkedList
and not some arbitrary outside user. It then becomes a question of interface design: Which parts of your code are implementation details and how those should be hidden from users? Which parts are the interface that users should interact with (with minimal opportunity for breaking things)?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With