help - compiler error - tried to wrap map iterator for keys and values

help - compiler error - tried to wrap map iterator for keys and values

Post by sks_cp » Mon, 28 Jul 2003 20:33:42



I am trying to wrap the map iterator for keys and values. However, I
seem to run into problems with the values for const_iterator - it works
for all other combinations.  Below I list my code and the compiler
error. Please help if possible. Thanks in advance.

// Compiler error ra:/home/ssangapu/personal/C++/STL/mapIter-738>g++
main.cc
utlMapIterator.h: In method `class Object *&
ValueIterator<_Rb_tree_iterator<pair<const int,Object *>,const
pair<const int,Object *> &,const pair<const int,Object *> *> >::operator
*()':

main.cc:84:   instantiated from here
utlMapIterator.h:27: conversion from `Object *const' to `Object *&'
discards qualifiers ra:/home/ssangapu/personal/C++/STL/mapIter-739>

//==================
// utlMapIterator.h
//==================
namespace utl
{
    template <bool flag, typename ThenType, typename ElseType>
    struct IF
    {
        typedef ThenType Result;
    };

    template <typename ThenType, typename ElseType>
    struct IF<false, ThenType, ElseType>
    {
        typedef ElseType Result;
    };

    template <typename T>
    class TypeTraits
    {
    private:
        template<class U>
        struct UnConst
        {
            typedef U Result;
            enum { isConst = false };
        };

        template<class U>
        struct UnConst<const U>
        {
            typedef U Result;
            enum { isConst = true };
        };

    public:

        enum { isConst = UnConst<T>::isConst };
    };

Quote:}

template <class MapIterator>
class ValueIterator : public MapIterator
{
public:

    typedef utl::IF< utl::TypeTraits<typename
MapIterator::reference>::isConst,
        const typename MapIterator::value_type::second_type&,
        typename MapIterator::value_type::second_type&>::Result
reference;

    typedef utl::IF< utl::TypeTraits<typename
MapIterator::pointer>::isConst,
        typename MapIterator::value_type::second_type* const,
        typename MapIterator::value_type::second_type*>::Result pointer;

    ValueIterator(const MapIterator& mIter) : MapIterator(mIter)
    { }

    reference operator*() // *************** ERROR HERE *************
    {
        return MapIterator::operator*().second;
    }

    pointer operator->()
    {
        return &**this;
    }

Quote:};

template <class MapIterator>
class KeyIterator : public MapIterator
{
public:

    typedef utl::IF< utl::TypeTraits<typename
MapIterator::reference>::isConst,
        const typename MapIterator::value_type::first_type&,
        typename MapIterator::value_type::first_type&>::Result
reference;

    typedef utl::IF< utl::TypeTraits<typename
MapIterator::pointer>::isConst,
        typename MapIterator::value_type::first_type* const,
        typename MapIterator::value_type::first_type*>::Result pointer;

    KeyIterator(const MapIterator& mIter) : MapIterator(mIter)
    { }

    reference operator*() const
    {
        return MapIterator::operator*().first;
    }

    pointer operator->() const
    {
        return &**this;
    }

Quote:};

template <class MapIterator>
inline
ValueIterator<MapIterator> valueIter(const MapIterator& iter)
{
    return ValueIterator<MapIterator>(iter);

Quote:}

template <class MapIterator>
inline
KeyIterator<MapIterator> keyIter(const MapIterator& iter)
{
    return KeyIterator<MapIterator>(iter);

Quote:}

//==================
// main.cc
//==================

#include <iostream>
#include <string>
#include <map>
#include <list>
#include <functional>
#include <algorithm>
#include <iterator>
#include "utlMapIterator.h"

using namespace std;

class Object
{
public:
    Object(int a) { i = a; }
    int i;

Quote:};

class Print
{
public:
    void operator()(Object* a)
    {
        cout << a->i << " ";
    }

Quote:};

int main()
{
    map<int, Object*> m_Map;
    Object o1(1*2);
    m_Map.insert(make_pair(1, &o1));

    Object o2(2*2);
    m_Map.insert(make_pair(2, &o2));

    Object o3(3*2);
    m_Map.insert(make_pair(3, &o3));

    Object o4(4*2);
    m_Map.insert(make_pair(4, &o4));

    Object o5(5*2);
    m_Map.insert(make_pair(5, &o5));

    Object o6(6*2);
    m_Map.insert(make_pair(6, &o6));

    cout << &o1 << " " << &o2 << " " << &o3 << " ";
    cout << &o4 << " " << &o5 << " " << &o6 << endl;

    cout << endl;
    cout << "Keys:\n";
    copy( keyIter(m_Map.begin()), keyIter(m_Map.end()),
ostream_iterator<int>(cout, " ") );
    cout << endl;

    cout << "Values:\n";
    for_each( valueIter(m_Map.begin()), valueIter(m_Map.end()), Print()
);
    cout << endl;
    cout << endl;

    cout << "Keys:\n";
    map<int, Object*>::const_iterator iter = m_Map.begin();
    for ( iter; iter != m_Map.end(); ++iter )
    {
        cout << *(keyIter(iter)) << "   ";
    }
    cout << endl;
    map<int, Object*>::iterator iter2 = m_Map.begin();
    for ( iter2; iter2 != m_Map.end(); ++iter2 )
    {
        cout << *(keyIter(iter2)) << "   ";
    }
    cout << endl;

    cout << "Values:\n";
    map<int, Object*>::const_iterator viter = m_Map.begin();
    for ( viter; viter != m_Map.end(); ++viter )
    {
        cout << (*valueIter(viter))->i << "   ";  // ************
COMPILER
ERROR ***************
    }
    map<int, Object*>::iterator viter2 = m_Map.begin();
    for ( viter2; viter2 != m_Map.end(); ++viter2 )
    {
        cout << (*valueIter(viter2))->i << "  ";
    }
    cout << endl;
    cout << endl;
    cout << endl;

    cout << "Copied to a list.\nValues:\n";
    list<Object*> myList;
    myList.insert( myList.end(),
                   valueIter(m_Map.begin()),
                   valueIter(m_Map.end()) );
    for_each( myList.begin(), myList.end(), Print() );

    cout << endl;
    cout << endl;

Quote:}

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
 
 
 

help - compiler error - tried to wrap map iterator for keys and values

Post by Ben Hutching » Wed, 30 Jul 2003 08:50:48



> I am trying to wrap the map iterator for keys and values. However, I
> seem to run into problems with the values for const_iterator - it works
> for all other combinations.  Below I list my code and the compiler
> error. Please help if possible. Thanks in advance.

> // Compiler error ra:/home/ssangapu/personal/C++/STL/mapIter-738>g++
> main.cc
> utlMapIterator.h: In method `class Object *&
> ValueIterator<_Rb_tree_iterator<pair<const int,Object *>,const
> pair<const int,Object *> &,const pair<const int,Object *> *> >::operator
> *()':

> main.cc:84:   instantiated from here
> utlMapIterator.h:27: conversion from `Object *const' to `Object *&'
> discards qualifiers ra:/home/ssangapu/personal/C++/STL/mapIter-739>

[utl::IF template class has bool, type, type parameters; Result member
typedef is second or third parameter depending on first parameter]

[utl::TypeTraits template has type parameter; isConst member enumerator
is true iff the parameter is const]

Quote:>     typedef utl::IF< utl::TypeTraits<typename
> MapIterator::reference>::isConst,
>         const typename MapIterator::value_type::second_type&,
>         typename MapIterator::value_type::second_type&>::Result
> reference;

>     typedef utl::IF< utl::TypeTraits<typename
> MapIterator::pointer>::isConst,
>         typename MapIterator::value_type::second_type* const,
>         typename MapIterator::value_type::second_type*>::Result pointer;

The problem with this is that a reference-to-const type is not itself
const-qualified.  Similarly a pointer-to-const type is not inherently
const-qualified.  You need to define another type-trait to detect one or
both of those.  Also you have the 'const' in the wrong place in the
definition of pointer - instead of
        typename MapIterator::value_type::second_type* const
you should have:
        const typename MapIterator::value_type::second_type*

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

 
 
 

1. Retrieve the key value from a map::iterator?

I have a map of strings [ map< string, string, less<string> >]. The main
use of the map is the normal one, accessing a value string given a key
string. That is,

   string value = theMap[key];

However, I have come across a case where I want to retrieve the key
values
in the map. It's easy enough to iterate over the map to process each
entry, but how can I get the key associated with each entry in the map?

   map<string, string, less<string> >::iterator i;
   for (i = theMap.begin(); i != theMap.end(); ++i)
   {
      string keyVal = ????;       // what goes here?
      ...
   }

I'm afraid it can't be done.

--
Jim Melton, novice guru           | So far as we know, our

v-mail: (303) 714-9732            | an undetected error.


      [ about comp.lang.c++.moderated. First time posters: do this! ]

2. plse help - more activesync problems

3. How do I use a list iterator as a map key

4. ISDN: RJ-11 vs. RJ-45

5. Using iterators as keys and such in maps...

6. 2 Nemeeting Sessions at the same time?

7. map order according to value (not key)

8. Problems With PPP

9. value when key doesn't exist in map ??

10. Maps that allow multiple values to a key

11. Mapping a class with member variable of value as the key

12. By using GDB, I want to display a value of map variable specified some key.

13. How to display map variable value by specifying some key with GDB?