tags:

views:

1824

answers:

3

I need help understanding some C++ operator overload statements. The class is declared like this:

template <class key_t, class ipdc_t>
class ipdc_map_template_t : public ipdc_lockable_t
{
    ...
    typedef map<key_t,
            ipdc_t*,
            less<key_t>> map_t;
    ...

The creator of the class has created an iterator for the internal map structure:

struct iterator : public map_t::iterator
{
    iterator() {}
    iterator(const map_t::iterator & it)
        : map_t::iterator(it) {}
    iterator(const iterator & it)
        : map_t::iterator(
            *static_cast<const map_t::iterator *>(&it)) {}
    operator key_t() {return ((this->operator*()).first);}           // I don't understand this.
    operator ipdc_t*() const {return ((this->operator*()).second);}  // or this.

};

And begin() and end() return the begin() and end() of the map:

iterator begin() {IT_ASSERT(is_owner()); return map.begin();}
iterator end() {return map.end();}

My question is, if I have an iterator, how do I use those overloads to get the key and the value?

ipdc_map_template_t::iterator iter;
 for( iter = my_instance.begin();
             iter != my_instance.end();
      ++iter )
 {
  key_t my_key = ??????;
  ipdc_t *my_value = ??????;

 }
+1  A: 

The creator of the class has overridden the cast operators. So by just assigning the iter to an object of the correct type it should auto cast itself via the methods into the correct values.

N.B.: The value type is being stored as a pointer. So when you extract the value you need to specify the pointer to the value type that you specified in the map interface.

 typedef ipdc_map_template_t<int,std::string>   MyMap;
 MyMap    mymap;

 for(MyMap::iterator iter = mymap.begin();
                     iter != mymap.end();
                     ++iter )
    {
            int          my_key   = iter;
            std::string* my_value = iter;

    }

Not sure I agree with the direction taken here. Does this make the code more readable? I would stick with the old fashioned map iterator sounds more usable. Is this container being defined in some specialized library that you need, or would it be beneficial to look at the boost pointer containers?

Martin York
Could you verify your code? I guess you're right but for one thing: The map is manipulating pointers of values, not values themselves. So I guess the user will have to do "std::string * my_value = iter;"... Or perhaps I should go sleep somewhat... :-p
paercebal
Just cought that. But it's hard to validate the code when you only get a partial definition of the class.
Martin York
Right... :-p ... Anyway, +1...
paercebal
+1  A: 

operator key_t() and operator ipdc_t*() are both cast definitions. So, given an iterator as defined in the class, you should be able to simply assign your variables:

ipdc_map_template_t::iterator iter;
    for( iter = my_instance.begin();
         iter != my_instance.end();
         ++iter )
    {
            key_t my_key = iter;
            ipdc_t my_value = iter;
    }
Caleb Huitt - cjhuitt
+6  A: 

These are typecast operators, so you can do this:

{
    key_t   key = iter;
    ipdc_t *val = iter;
}

Or, since ipdc_map_template::iterator is a subclass of std::map::iterator, you can still use the original accessors (which I find more readable):

{
    key_t   key = (*iter).first;
    ipdc_t *val = (*iter).second;

    // or, equivalently
    key_t   key = iter->first;
    ipdc_t *val = iter->second;

}
iter->first looks better than (*iter).first IMO, since it gets rid of the need for parentheses.
Greg Rogers
I like Greg's version, but, anyway, you're right about the readability of using std::map standard interface instead of hacking one's way through misuse of cast operator overloading...
paercebal