[iterator_facade] Help with const iterator for binary file

Hi, I have a class modeling a record-based read-only binary file and I have written a random access iterator based on iterator_facade to iterate over the records. The class looks like this: class my_binary_file { public: typedef std::string key_type; typedef unsigned int value_type; typedef std::pair<key_type, value_type> record_type; private: class my_binary_file_iterator : public boost::iterator_facade< my_binary_file_iterator, my_binary_file::record_type const, boost::random_access_traversal_tag, my_binary_file::record_type&, int> { public: my_binary_file_iterator() : rec_num_(0), ff_ptr_(0) { } explicit my_binary_file_iterator(my_binary_file* ff, unsigned int n) : ff_ptr_(ff), rec_num_(n) { } private: friend class boost::iterator_core_access; unsigned int rec_num_; my_binary_file* ff_ptr_; mutable my_binary_file::record_type record; void increment() { ++rec_num_; } void decrement() { --rec_num_; } void advance(int n) { rec_num_ += n; } int distance_to(const my_binary_file_iterator z) const { return z.rec_num_ - this->rec_num_; } bool equal(my_binary_file_iterator const& other) const { return this->ff_ptr_ == other.ff_ptr_ && this->rec_num_ == other.rec_num_; } const my_binary_file::record_type dereference() const { ff_ptr_->seekg(rec_num_); my_binary_file::key_type key; my_binary_file::value_type val; ff_ptr_->get_record(key, val); record = std::make_pair(key, val); return record; } }; public: typedef my_binary_file_iterator iterator; iterator begin() const { return iterator(this, 0); } iterator end() const { return iterator(this, num_records_); } // Opens a binary file for reading explicit my_binary_file(const std::string& path); ~my_binary_file(); operator void*() const; bool operator!() const; // Reads the record at the current position bool get_record(key_type& k, value_type& v); std::ios::pos_type tellg() const { return fs_.tellg(); } void seekg(unsigned int n) { fs_.seekg(start_record_ + std::ios::off_type(n * record_size_), std::ios::beg); } private: boost::filesystem::path pathname_; mutable boost::filesystem::fstream fs_; std::streampos start_record_; key_type::size_type key_size_; unsigned int record_size_, num_records_; }; Unfortunately, when I try to compile my project, I get the following error: error: invalid conversion from 'const frequency_file* const' to 'frequency_file*' I have tried several variants of my code, but without success. I think I'm missing something pretty obvious in my definition of my_binary_file_iterator, but I can't get out of it. Anyone can help? Regards Nicola

In article <vitacolo-E2DC4C.21463511012008@ger.gmane.org>, nicola <vitacolo@dimi.uniud.it> wrote:
[...] Unfortunately, when I try to compile my project, I get the following error:
error: invalid conversion from 'const frequency_file* const' to 'frequency_file*'
Of course, the error message should read: error: invalid conversion from 'const my_binary_file* const' to 'my_binary_file*' Nicola

AMDG nicola wrote:
Hi, I have a class modeling a record-based read-only binary file and I have written a random access iterator based on iterator_facade to iterate over the records. The class looks like this:
class my_binary_file {
<snip>
explicit my_binary_file_iterator(my_binary_file* ff, unsigned int n) : ff_ptr_(ff), rec_num_(n) { }
my_binary_file* is *not* const here.
<snip>
};
public: typedef my_binary_file_iterator iterator;
iterator begin() *const* { return iterator(this, 0); }
this is a pointer to const. The constructor of iterator requires a pointer to non-const. In Christ, Steven Watanabe

In article <478810E0.7030407@providere-consulting.com>, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
nicola wrote:
Hi, I have a class modeling a record-based read-only binary file and I have written a random access iterator based on iterator_facade to iterate over the records. The class looks like this:
class my_binary_file {
<snip>
explicit my_binary_file_iterator(my_binary_file* ff, unsigned int n) : ff_ptr_(ff), rec_num_(n) { }
my_binary_file* is *not* const here.
Thanks for pointing that out. In the tutorial example at http://www.boost.org/libs/iterator/doc/iterator_facade.html#tutorial-exam ple sect. "A constant node_iterator", shouldn't the constructor's parameter of const_node_iterator be const? That is, explicit const_node_iterator(const /* <== ? */ node_base* p) : m_node(p) {}
<snip>
};
public: typedef my_binary_file_iterator iterator;
iterator begin() *const* { return iterator(this, 0); }
this is a pointer to const. The constructor of iterator requires a pointer to non-const.
There is more than that, however: as you can see in my original post, get_record() and seekg() are not const and that is a problem because they are invoked by dereference(). I can compile successfully if I const-qualify them, but this is not correct in my opinion. The fact is, they do change the state of the object in a visible way. That's the implementation of get_record() that I had omitted in the original post (but that you could have easily guessed): bool get_record(key_type& k, value_type& v) /* const ??? */ { if (fs_.read(reinterpret_cast<char*>(&k), key_size_)) { if (fs_.read(reinterpret_cast<char*>(&v), sizeof(value_type))) { return true; } } return false; } So, for example, calling get_record() twice results in two consecutive records to be read — not the same record. Moreover, I will be interested, at a later stage, in extending the class so that it can read and *write* files. Is there any better solution than using const member functions for my get_record() and seekg()? Nicola

AMDG nicola wrote:
There is more than that, however: as you can see in my original post, get_record() and seekg() are not const and that is a problem because they are invoked by dereference(). I can compile successfully if I const-qualify them, but this is not correct in my opinion. The fact is, they do change the state of the object in a visible way.
OK. Since begin and end return handles to the class that allow its state to change they should not be const. If they absolutely need to be const then you need to reset the the seek position after you use it. You can create private const versions get_record and seekg for this purpose. In Christ, Steven Watanabe
participants (2)
-
nicola
-
Steven Watanabe