0

I am trying to save an instance of my custom class to a vector, but I get the following error during compilation:

error: binding 'const anil::cursor_list' to reference of type 'anil::cursor_list&' discards qualifiers
 { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }

Could you help me figure what I'm doing wrong?

The snippet of code that triggers this is as follows:

std::vector<anil::cursor_list> strongly_connected_components;
anil::cursor_list strongly_connected_component_list;
strongly_connected_components.push_back(strongly_connected_component_list);

The declaration for this class is as follows:

#include <cstddef>
#include <iostream>

namespace anil {
  class cursor_list_node {
    private:
      int data;
      cursor_list_node* next;
      cursor_list_node* previous;
      friend class cursor_list; 
  };

  class cursor_list {
    private:

      // Data:
      int m_index;
      int m_size;
      cursor_list_node* front;
      cursor_list_node* back;
      cursor_list_node* cursor;
      
      int m_backup_index;
      cursor_list_node* backup_cursor;

      // Functions:
      void delete_list();

    public:
      cursor_list() : m_index(-1), m_size(0), front(nullptr), back(nullptr),
        cursor(nullptr), m_backup_index(-1), backup_cursor(nullptr) {}
      cursor_list(cursor_list& copied_list);
      bool is_empty();
      int size();
      int index();
      int front_data();
      int back_data();
      int cursor_data();
      bool operator==(cursor_list& rhs); // rhs = right hand side
      cursor_list& operator= (cursor_list& rhs);  // rhs = right hand side
      friend std::ostream& operator<<(std::ostream& out, cursor_list& rhs); // rhs = right hand side
      void clear();
      void move_cursor_front();
      void move_cursor_back();
      void move_cursor_prev();
      void move_cursor_next();
      void save_cursor_state();
      void restore_cursor_state();
      void prepend(int new_data);
      void append(int new_data);
      void insert_before_cursor(int new_data);
      void insert_after_cursor(int new_data);
      void delete_front();
      void delete_back();
      void delete_cursor();
      ~cursor_list();
  };
}

Lastly, the constructors for the cursor_list class are as follows:

cursor_list() : m_index(-1), m_size(0), front(nullptr), back(nullptr),
        cursor(nullptr), m_backup_index(-1), backup_cursor(nullptr) {}

anil::cursor_list::cursor_list(cursor_list& copied_cursor_list) {
  this->m_index = -1;
  this->m_size = 0;
  this->front = nullptr;
  this->back = nullptr;
  this->cursor = nullptr;
  this->m_backup_index = -1;
  this->backup_cursor = nullptr;
  if (copied_cursor_list.is_empty() == false) {
    for (cursor_list_node* it = copied_cursor_list.front; it != nullptr;
         it = it->next) {
      this->append(it->data);
    }
  }
}

Edit:

By following prog-fh's explanations and suggestions, I was able to solve the problem described above.

I achieved this by changing the parameter for the copy constructor from cursor_list& copied_cursor_list to const cursor_list& copied_cursor_list and changing the pointer that I used to copy the values of the list from cursor_list_node* it to const cursor_list_node* it.

Anil Celik Maral
  • 177
  • 1
  • 12
  • 2
    Looks like you're attempting to make a non-`const` reference to a `const` object. Your copy constructor should accept a `const cursor_list&`. – Fred Larson Aug 23 '21 at 13:40
  • 2
    [Why C++ copy constructor must use const object?](https://stackoverflow.com/questions/16956693/why-c-copy-constructor-must-use-const-object) – Drew Dormann Aug 23 '21 at 13:47

1 Answers1

2

push_back() makes a copy, but your copy-constructor expects a cursor_list& copied_cursor_list parameter. The parameter should be const cursor_list& copied_cursor_list. (See the documentation, the parameter for push_back() is const &).

Actually, the problem is similar with the copy-assign operator (should be cursor_list& operator= (const cursor_list& rhs);).

By the way, your cursor_list type should probably have some const-qualified member functions (is_empty(), size()...) in order to make them usable on an immutable object. One should consider const-correctness from the beginning; it is difficult to fix it afterwards.


To answer the question in the comments, if the copy constructor was anil::cursor_list::cursor_list(const cursor_list& copied_cursor_list) (as expected), you would have a problem when invoking copied_cursor_list.is_empty() because copied_cursor_list is supposed to be const but the is_empty() member-function does not make the promise « I won't mutate *this ». In order to fix this, you need to declare (and define as well) bool is_empty() const; (the const at the end of the prototype applies to *this).

prog-fh
  • 13,492
  • 1
  • 15
  • 30
  • Could you give a couple of examples on how to make the parameters work for a const qualified member? Or could you direct me to a good example. I am a novice in C++ so I don't quite know how to do it. I tried to implement the copy constructor with `const cursor_list& rhs` as its parameter but got compilation errors due to modifying a const object so I removed it. – Anil Celik Maral Aug 23 '21 at 13:55
  • 1
    @AnilCelikMaral it is suspect that your code to _copy an object_ also tries to _change_ that object. I am guessing that you have mistakes in that code. – Drew Dormann Aug 23 '21 at 14:06
  • @DrewDormann I need to use the member `cursor_list_node* cursor` to traverse the list and copy its members to a new list. That means I need to modify `cursor_list_node* cursor`. How could I do this for a const object or what other way could I use to copy the members of a list to a new list without violating the rules of a const object? – Anil Celik Maral Aug 23 '21 at 14:10
  • 1
    @AnilCelikMaral You could use `const cursor_list_node* it` to iterate without taking the risk of mutating the visited `cursor_list_node`s. Note also that, `std::list` (or even better `std::vector`) could be much easier than hand-managing your own linked-list. – prog-fh Aug 23 '21 at 14:15
  • @prog-fh Thanks a lot for all of the answers and insights! Really appreciated :) I will try to make the changes that you've suggested so far and will post the updated results as edits to the main question. I check those two STL classes to see if I can integrate them to my graph class. Maybe that will be my next project :) – Anil Celik Maral Aug 23 '21 at 14:22