In the below code we try to multiply each element’s data in the list by 2 and assign it. But the apply function is a const function therefore should not be able to change the values of member fields. Output for the fifth line in main is
6
4
2
2
4
So code below succeeds in changing the values as intended and I can’t figure out why.
#include <iostream>
#include <list>
#include <string>
using std::ostream;
using std::cout;
using std::endl;
template<class E> class MyList {
class Node {
friend class MyList<E>;
E data;
Node* next = nullptr;
}; // end of class Node
Node* head = new Node;
Node* tail = head;
MyList(const MyList&) = default;
public:
MyList() = default;
MyList& operator=(const MyList&) = delete;
void push_front(const E& data) {
Node* node = new Node;
node->data = data;
node->next = head->next;
head->next = node;
if(head->next == nullptr) tail = node;
}
void push_back(const E& data) {
if(head->next == nullptr) {
push_front(data); return;
}
MyList temp(*this);
temp.head = temp.head->next;
temp.push_back(data);
temp.head = nullptr;
}
~MyList() {
Node *node = head, *next;
while(node != nullptr) {
next = node->next;
delete node;
node = next;
}
}
template<class Function>
void apply (Function f) const {
Node* node = head->next;
while(node != nullptr) {
f(node->data);
node = node->next;
}
}
};
int main() {
MyList<int> m1;
m1.push_back(3);
for(int i = 1; i <= 2; ++i) m1.push_front(i);
for(int i = 1; i <= 2; ++i) m1.push_back(i);
m1.apply(
[](auto& val){ val *= 2;}
);
m1.apply(
[](const auto& val){cout << val << endl;}
);
return 0;
}
>Solution :
The key is logical vs bitwise constness. The head data member is a non-const pointer to non-const Node: the const correctness of the apply member function is bitwise constness:
- you cannot change what the
headdata member (pointer) points to from a const-qualified member function.
You can, however, mutate the Node object that it points to.