Connecting Tech Pros Worldwide Help | Site Map

Return an iterator?

Markus Dehmann
Guest
 
Posts: n/a
#1: Jul 22 '05
I have a class Foo that contains a map<string,string> internally. Now,
I want that users can iterate over the entries in the map. What's the
best way to do that?

I tried a method like
map<string,string>::const_iterator get_const_iterator(){
return my_map.begin();
}
but then users also need to know where the end() of the map is in
order to for-loop over the elements.

So, do I have to provide a begin() and end() method in my Foo class?
Or is there a better solution?

Thanks
Markus
Daniel T.
Guest
 
Posts: n/a
#2: Jul 22 '05

re: Return an iterator?


In article <c1e48b51.0408101347.4050f5ed@posting.google.com >,
markus.cl@gmx.de (Markus Dehmann) wrote:
[color=blue]
> I have a class Foo that contains a map<string,string> internally. Now,
> I want that users can iterate over the entries in the map. What's the
> best way to do that?
>
> I tried a method like
> map<string,string>::const_iterator get_const_iterator(){
> return my_map.begin();
> }
> but then users also need to know where the end() of the map is in
> order to for-loop over the elements.
>
> So, do I have to provide a begin() and end() method in my Foo class?
> Or is there a better solution?[/color]

Nope, that's it:

class Class {
map<string, string> my_map;
public:
typedef map<string, string>::const_iterator const_iterator;
const_iterator begin() const {
return my_map.begin();
}
const_iterator end() const {
return my_map.end();
}
};
Bob Hairgrove
Guest
 
Posts: n/a
#3: Jul 22 '05

re: Return an iterator?


On 10 Aug 2004 14:47:31 -0700, markus.cl@gmx.de (Markus Dehmann)
wrote:
[color=blue]
>I have a class Foo that contains a map<string,string> internally. Now,
>I want that users can iterate over the entries in the map. What's the
>best way to do that?
>
>I tried a method like
>map<string,string>::const_iterator get_const_iterator(){
> return my_map.begin();
>}[/color]

(BTW this function should be const...you cannot modify the map through
a const_iterator, hence you should be able to call it on const Foo
objects.)
[color=blue]
>but then users also need to know where the end() of the map is in
>order to for-loop over the elements.
>
>So, do I have to provide a begin() and end() method in my Foo class?
>Or is there a better solution?
>[/color]

Another (IMHO better) solution would be to provide const access to the
map itself, i.e. a member function such as:

const map<string,string> & the_map() const { return my_map; }


--
Bob Hairgrove
NoSpamPlease@Home.com
David Hilsee
Guest
 
Posts: n/a
#4: Jul 22 '05

re: Return an iterator?


"Bob Hairgrove" <invalid@bigfoot.com> wrote in message
news:7mjih05gvea010c69940jljk1dq8e8epfo@4ax.com...
[snip][color=blue]
> Another (IMHO better) solution would be to provide const access to the
> map itself, i.e. a member function such as:
>
> const map<string,string> & the_map() const { return my_map; }[/color]

The begin()/end() approach buys you a little flexibility if you ever decide
to drop std::map to use a different container. In theory, one could replace
the container and provide an iterator that provided the same interface as
std::map::const_iterator. That's not a big deal for small programs, so your
suggestion is probably just as good.

--
David Hilsee


Siemel Naran
Guest
 
Posts: n/a
#5: Jul 22 '05

re: Return an iterator?


"Markus Dehmann" <markus.cl@gmx.de> wrote in message
[color=blue]
> I have a class Foo that contains a map<string,string> internally. Now,
> I want that users can iterate over the entries in the map. What's the
> best way to do that?[/color]
[color=blue]
> So, do I have to provide a begin() and end() method in my Foo class?
> Or is there a better solution?[/color]

Yes, that's one way as others pointed out. There are 2 other ways I've
used. Though neither way is superior to the others, and I've used all of
them in my own code:

(2) Write a nested class Foo::MapIterator that contains private members
d_begin and d_end pointing to the begin and end of the map. There will be a
functions Foo::MapIterator::valid() const or the like to tell if the
iterator is valid, Foo::MapIterator::operator++() etc.

Foo::MapIterator iter = foo.mapiterator();
for ( ; iter.valid(); ++iter) {
/* do stuff */
}

Unfortunately, in this method you cannot use standard algorithms and others
from boost which expect two iterator arguments. But if you don't need the
generality, then this method is fine.

(3) Provide a template function Foo::for_each_element_in_map.

template <class Oper>
void Foo::for_each_element_in_map(const Oper& oper) {
std::for_each(d_map.begin(), d_map.end(), oper);
}


Bob Hairgrove
Guest
 
Posts: n/a
#6: Jul 22 '05

re: Return an iterator?


On Tue, 10 Aug 2004 20:13:00 -0400, "David Hilsee"
<davidhilseenews@yahoo.com> wrote:
[color=blue]
>"Bob Hairgrove" <invalid@bigfoot.com> wrote in message
>news:7mjih05gvea010c69940jljk1dq8e8epfo@4ax.com.. .
>[snip][color=green]
>> Another (IMHO better) solution would be to provide const access to the
>> map itself, i.e. a member function such as:
>>
>> const map<string,string> & the_map() const { return my_map; }[/color]
>
>The begin()/end() approach buys you a little flexibility if you ever decide
>to drop std::map to use a different container. In theory, one could replace
>the container and provide an iterator that provided the same interface as
>std::map::const_iterator.[/color]

I'm not so sure ... map<> is a peculiar beast (behavior of its
operator[] compared to vector::operator[], for example). Clients will
probably want to know the exact type of container they are using,
especially if it's a map.

If you really want to replace the container, you could also provide a
typedef for it and merely change the typedef.

--
Bob Hairgrove
NoSpamPlease@Home.com
Richard Herring
Guest
 
Posts: n/a
#7: Jul 22 '05

re: Return an iterator?


In message <06jjh0dfe6eefi79e2jabgk4lqq3fj7sv3@4ax.com>, Bob Hairgrove
<invalid@bigfoot.com> writes[color=blue]
>On Tue, 10 Aug 2004 20:13:00 -0400, "David Hilsee"
><davidhilseenews@yahoo.com> wrote:
>[color=green]
>>"Bob Hairgrove" <invalid@bigfoot.com> wrote in message
>>news:7mjih05gvea010c69940jljk1dq8e8epfo@4ax.com. ..
>>[snip][color=darkred]
>>> Another (IMHO better) solution would be to provide const access to the
>>> map itself, i.e. a member function such as:
>>>
>>> const map<string,string> & the_map() const { return my_map; }[/color]
>>
>>The begin()/end() approach buys you a little flexibility if you ever decide
>>to drop std::map to use a different container. In theory, one could replace
>>the container and provide an iterator that provided the same interface as
>>std::map::const_iterator.[/color]
>
>I'm not so sure ... map<> is a peculiar beast (behavior of its
>operator[] compared to vector::operator[], for example). Clients will
>probably want to know the exact type of container they are using,
>especially if it's a map.[/color]

I'd have said it depends entirely on the interface (at the Concept
level) you _choose_ to present to the clients. You may be using a map
internally for your own nefarious purposes, but if you present the data
conceptually to them as a non-modifiable sequence accessible only by
const forward (or maybe bidirectional) iterators, they have no reason to
know or care about the underlying map.
[color=blue]
>
>If you really want to replace the container, you could also provide a
>typedef for it and merely change the typedef.
>
>--
>Bob Hairgrove
>NoSpamPlease@Home.com[/color]

--
Richard Herring
Closed Thread