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 };
};
}
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;
}
};
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;
}
};
template <class MapIterator>
inline
ValueIterator<MapIterator> valueIter(const MapIterator& iter)
{
return ValueIterator<MapIterator>(iter);
}
template <class MapIterator>
inline
KeyIterator<MapIterator> keyIter(const MapIterator& iter)
{
return KeyIterator<MapIterator>(iter);
}
//==================
// 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;
};
class Print
{
public:
void operator()(Object* a)
{
cout << a->i << " ";
}
};
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;
}