Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How did this loophole around const member function worked?

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;
}

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>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 head data member (pointer) points to from a const-qualified member function.

You can, however, mutate the Node object that it points to.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading