maps, iterators, and const

J

John

Hi,

I have the following classes

class A {};

class B
{
std::map<int,A*> mmap;

public:
std::map<int,A*>::const_iterator begin() const
{ return mmap.begin(); }
std::map<int,A*>::const_iterator end() const
{ return mmap.end(); }
}

Since end/begin return const_iterators, I know that the keys of the map
cannot be changed. Also, the pointers in the values of the map cannot
be changed. However, the A objects being pointed to can be altered.
What I would like is to be able to return an iterator to the map and
protect not only the map itself but keep for the pointer to be constant
as well, i.e., const A*. Or in other words, have behavior like

std::map<int,const A*>::const_iterator begin() const
{ return mmap.begin(); }

even though mmap internally is actually std::map<int,A*> .

Is there any way to do this (preferably without using const_cast). I
have tried a number of things, but can't seem to get it right.


Thanks,
John
 
J

John

Solve this by creating your own iterators which inherit privately from
the map's iterators and don't expose the map's iterators in your custom
interface.

/Leigh

Hmm. This would be more complicated than I would like since I don't
want to have to define additional classes. It's not ideal, but maybe I
will just go the const_cast route and define my map as
std::map<int,const A*> and use const_cast internally in the few places I
need to alter an A.

Thanks,
John
 
A

Alf P. Steinbach

* John, on 21.05.2010 17:54:
Hmm. This would be more complicated than I would like since I don't want
to have to define additional classes. It's not ideal, but maybe I will
just go the const_cast route and define my map as std::map<int,const A*>
and use const_cast internally in the few places I need to alter an A.

Possibly you have design level problem, but possibly you have not.

You might consider something like the following:


<code>
#include <map>
#include <iostream>

class A {};

class B
{
typedef std::map< int, A* > Map;
Map map_;

B( B const& other );
B& operator=( B const& other );

public:
B()
{
map_[1] = new A;
map_[2] = new A;
map_[3] = new A;
}

class ConstIter
{
friend class B;
private:
typedef std::pair< int, A const* > ConstPair;
Map::const_iterator current_;

ConstIter( Map::const_iterator start )
: current_( start )
{}

ConstPair const* operator->() const; // No such.

public:
ConstIter& operator++()
{
++current_; return *this;
}

ConstIter operator++( int )
{
return ConstIter( current_++ );
}

ConstPair const operator*() const
{
return *current_;
}

bool operator==( ConstIter const& other )
{
return current_ == other.current_;
}

bool operator!=( ConstIter const& other )
{
return current_ != other.current_;
}

int key() const { return current_->first; }
A const* value() const { return current_->second; }
};

ConstIter begin() const { return map_.begin(); }
ConstIter end() const { return map_.end(); }
};

int main ()
{
B b;
for( B::ConstIter it = b.begin(); it != b.end(); ++it )
{
std::cout << it.key() << std::endl;
}
}
</code>


Cheers & hth.,

- Alf
 
J

John

Alf said:
* John, on 21.05.2010 17:54:

Possibly you have design level problem, but possibly you have not.

Yes, that is always very likely in my code.
You might consider something like the following:
snip


</code>


Cheers & hth.,

- Alf

Thanks Alf. I can get the same effect with two const_cast uses in my
class functions. I will have to consider whether the derived iterators
are the route I want to go. The code is certainly instructive though as
I've never implemented my own iterators.

John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top