1

Passing an object by const reference means we can't modify any of it's members. But suppose the object contains a vector<string> member. How do we write const methods to read the contents of the vector<string> member assuming that a vector<string>::iterator member is also needed and must be updated after every read to point to the next element in the vector?

Is this possible, or is there another method in this situation? That is, don't modify the contents of the passed by const reference object, but the object should be able to update it's internal state (i.e. next element in the vector to be read).

mihai
  • 4,592
  • 3
  • 29
  • 42
  • Can you use `vector::const_iterator` to iterate over the vector instead? – simonc Oct 17 '13 at 16:29
  • I'm trying to modify the iterator, which is a member of an object passed by const reference (i.e. I can't modify it). Declare the member as mutable seems to be the answer, as others have pointed out. – mihai Oct 17 '13 at 16:43
  • If you want to modify it, why are you passing it as `const&`? – John Dibling Oct 17 '13 at 16:50
  • I actually want to read it, but I don't know how to except keep an iterator as a member of the passed by const reference object and increment it after each read. Are there any other methods? – mihai Oct 17 '13 at 17:26

3 Answers3

2

It sounds like you are looking for the keyword mutable. A mutable member variable is modifyable within a const member method. You can read about it here. An example:

class A
{
    std::vector< int > v_;
    mutable std::vector< int >::const_iterator current_;

public:
    int get() const // note the const
    {
        assert( !v_.empty() );
        if( current_ == v_.end() ) current_ = v_.begin();
        return *current_++;
    }
};

Note you still need const_iterator as the vector itself is const and hence v_.begin() does not give you a normal iterator. You could fix this by marking the vector itself also as mutable, then you could use iterator.

Here's a complete live example.

Daniel Frey
  • 55,810
  • 13
  • 122
  • 180
  • it_ should be current_, right? Yes, that sounds like the solution I was looking for. But I'm getting an "error: no match for 'operator='" when I try to set the iterator at the beginning of the vector (it_ = v_.begin()) inside the const method. – mihai Oct 17 '13 at 16:41
  • Answers the question, but my hack-o-meter is twitching. Can't upvote as it skirts what is likely the *real* problem. – John Dibling Oct 17 '13 at 16:50
  • @JohnDibling Understandable. For the OP I think it's important to know about the existance of `mutable` first, but it's hard to tell whether or not it's a *good* solution in his case. The problem description itself looked kind of odd to me, in real-life I'd question the design that lead to this question first :) – Daniel Frey Oct 17 '13 at 16:54
  • Ok, making the passed by const reference object into a member of the object it was passed into a better solution? I was trying to keep my code as modular as possible. If it's a beast then I accept the punishment :) Is the use of mutable frowned upon? – mihai Oct 17 '13 at 17:18
  • @Mihai Generally, using `mutable` is sometimes good and sometimes a sign of bad design. With the information we have about your problem, I really can't tell. I would think that it's probably *not* the best solution here, but I don't have enought information to offer a better alternative. I suggest you learn about how `mutable` works and then you need to make your own decision. – Daniel Frey Oct 17 '13 at 17:28
1

If you have a member you wish to modify at const methods - declare them mutable.

Ivan Ishchenko
  • 1,468
  • 9
  • 12
0

Do not do it: If you want to have semantics like first(), next(), last() for iterating a container, create a proxy:

Proxy iteration() const { return Proxy(*this); }