map of pointers inside another map raise exception

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

map of pointers inside another map raise exception

Postby Emily W. Haley » Sun Jun 07, 2020 6:05 am

Hi, All

I have created my own std::map wrapper because it makes some of my tasks simpler this way.
The code for the wrapper:
Code: Select all
//---------------------------------------------------------------------------
#ifndef MapListH
#define MapListH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <System.SysUtils.hpp>
#include "ClangCpp.h"
#include <string.h>
#include <map>
//---------------------------------------------------------------------------
//New Events
//---------------------------------------------------------------------------
template <class Key, class Value>
class TMapList
{
protected:
typedef std::pair<Key,Value> PairType;
typedef void __fastcall (__closure *TForEachItem)(Key Index, Value Item);
typedef void __fastcall (__closure *TItemClear)(Key Index, Value Item);
typedef typename std::map<Key,Value>::iterator TMapListIterator;

private:
//Events
TItemClear FOnItemClear;

//---------------------------------------------------------------------------
protected:
//Setters/Getters
virtual int __fastcall GetCount() const;
virtual void __fastcall SetElement(Key Index, const Value& Item);
virtual Value __fastcall GetElement(Key Index) const;
virtual void __fastcall SetElementByIndex(int Index, const Value& Item);
virtual Value __fastcall GetElementByIndex(int Index) const;
virtual Key __fastcall GetKeyByIndex(int Index) const;
virtual Key __fastcall GetKeyByValue(Value Item) const;

//Do Events Methods
virtual void __fastcall DoItemClear(Key Index, Value Item);

//---------------------------------------------------------------------------
public:
//Fields/Properties
mutable std::map< Key, Value> Map;

mutable typename std::map<Key,Value>::iterator Iter;
__property int Count = {read = GetCount};
__property Value Item[Key Index] = {read = GetElement, write = SetElement};
__property Value ItemByIndex[int Index] = {read = GetElementByIndex, write = SetElementByIndex};
__property Key KeysByIndex[int Index] = {read = GetKeyByIndex};
__property Key KeyByValue[Value Item] = {read = GetKeyByValue};

//Constructor / Destructor.
__fastcall TMapList() {FOnItemClear = nullptr;};
virtual __fastcall ~TMapList(void);

//Methods
virtual void __fastcall First() const;
virtual void __fastcall Last() const;
virtual void __fastcall IncIter();
virtual void __fastcall Add(Key Index, const Value& Item);
virtual bool __fastcall Exists(Key Index) const;
virtual typename std::map<Key,Value>::iterator __fastcall FindIter(Key Index) const;
virtual bool __fastcall Find(Key Index, Value& Item) const;
virtual bool __fastcall Find(Key Index) const;
virtual bool __fastcall TillEnd() const;
virtual bool __fastcall ValueExists(Value Item) const;
virtual Value __fastcall Delete(Key Index);
virtual bool __fastcall Empty() const;
//Methods
virtual void __fastcall ForEachItem(TForEachItem ForEachItemEvent);

virtual void __fastcall Clear();

inline bool operator == (const TMapList& MapListValue) const
{
return (Map == MapListValue.Map);
}
//--------------------------------

//Events
__property TItemClear OnItemClear= {read = FOnItemClear, write = FOnItemClear};
};
//---------------------------------------------------------------------------
typedef std::map<String,String> TStrsMap;

typedef std::pair<int,int> TIntToIntPair;
typedef std::pair<int,String> TIntToStrPair;
typedef std::pair<String,String> TStrToStrPair;
typedef std::pair<String,int> TStrToIntPair;

typedef TMapList<int,int> TIntToIntMap;
typedef TMapList<int,String> TIntToStrMap;
typedef TMapList<String,String> TStrToStrMap;
typedef TMapList<String,int> TStrToIntMap;
//---------------------------------------------------------------------------
template <class Key, class Value>
int __fastcall TMapList<Key,Value>::GetCount() const
{
return Map.size();
}
//---------------------------------------------------------------------------
template <class Key, class Value>
void __fastcall TMapList<Key,Value>::SetElement(Key Index, const Value& Item)
{
Map[Index] = Item;
}
//---------------------------------------------------------------------------
template <class Key, class Value>
Value __fastcall TMapList<Key,Value>::GetElement(Key Index) const
{
return Map[Index];
}
//---------------------------------------------------------------------------
template <class Key, class Value>
void __fastcall TMapList<Key,Value>::SetElementByIndex(int Index, const Value& Item)
{
Iter = Map.begin();
std::advance(Iter, Index);
Iter->second = Item;
}
//---------------------------------------------------------------------------
template <class Key, class Value>
Value __fastcall TMapList<Key,Value>::GetElementByIndex(int Index) const
{
Iter = Map.begin();
std::advance(Iter, Index);
return Iter->second;
}
//---------------------------------------------------------------------------
template <class Key, class Value>
Key __fastcall TMapList<Key,Value>::GetKeyByIndex(int Index) const
{
Iter = Map.begin();
std::advance(Iter, Index);
return Iter->first;
}
//---------------------------------------------------------------------------
template <class Key, class Value>
Key __fastcall TMapList<Key,Value>::GetKeyByValue(Value Item) const
{
Key res;

for (Iter = Map.begin(); Iter != Map.end(); ++Iter )
   {
   if (Iter->second == Item)
      {
      res = Iter->first;
      break;
      }
   }
return res;
}
//---------------------------------------------------------------------------
template <class Key, class Value>
void __fastcall TMapList<Key,Value>::DoItemClear(Key Index, Value Item)
{
if (FOnItemClear)
   FOnItemClear(Index, Item);
}
//---------------------------------------------------------------------------
template <class Key, class Value>
__fastcall TMapList<Key,Value>::~TMapList(void)
{
Clear();
}
//---------------------------------------------------------------------------
template <class Key, class Value>
void __fastcall TMapList<Key,Value>::First() const
{
this->Iter = this->Map.begin();
}
//---------------------------------------------------------------------------
template <class Key, class Value>
void __fastcall TMapList<Key,Value>::Last() const
{
this->Iter = this->Map.end();
}
//---------------------------------------------------------------------------
template <class Key, class Value>
void __fastcall TMapList<Key,Value>::IncIter()
{
++Iter;
}
//---------------------------------------------------------------------------
template <class Key, class Value>
bool __fastcall TMapList<Key,Value>::TillEnd() const
{
return (this->Iter != this->Map.end());
}
//---------------------------------------------------------------------------
template <class Key, class Value>
void __fastcall TMapList<Key,Value>::Add(Key Index, const Value& Item)
{
Map.insert(std::make_pair( Index, Item));
}
//---------------------------------------------------------------------------
template <class Key, class Value>
bool __fastcall TMapList<Key,Value>::Exists(Key Index) const
{
return Map.count(Index);
}
//---------------------------------------------------------------------------
template <class Key, class Value>
typename std::map<Key,Value>::iterator __fastcall TMapList<Key,Value>::FindIter(Key Index) const
{
return Map.find(Index);
}
//---------------------------------------------------------------------------
template <class Key, class Value>
bool __fastcall TMapList<Key,Value>::Find(Key Index, Value& Item) const
{
Iter = Map.find(Index);

if (Iter != Map.end())
   {
   Item = Iter->second;
   return true;
   }
else
   return false;
}
//---------------------------------------------------------------------------
template <class Key, class Value>
bool __fastcall TMapList<Key,Value>::Find(Key Index) const
{
Iter = Map.find(Index);
return (Iter != Map.end());
}
//---------------------------------------------------------------------------
template <class Key, class Value>
bool __fastcall TMapList<Key,Value>::ValueExists(Value Item) const
{
for (Iter = Map.begin(); Iter != Map.end(); ++Iter )
   {
   if (Iter->second == Item)
      return true;
   }
return false;
}
//---------------------------------------------------------------------------
template <class Key, class Value>
Value __fastcall TMapList<Key,Value>::Delete(Key Index)
{
Value temp = Item[Index];
Map.erase(Index);
return temp;
}
//---------------------------------------------------------------------------
template <class Key, class Value>
bool __fastcall TMapList<Key,Value>::Empty() const
{
return (GetCount() == 0);
}
//---------------------------------------------------------------------------
template <class Key, class Value>
void __fastcall TMapList<Key,Value>::ForEachItem(TForEachItem ForEachItemEvent)
{
for (Iter=Map.begin(); Iter !=Map.end(); ++Iter)
   {
   ForEachItemEvent(Iter->first, Iter->second);
   }
}
//---------------------------------------------------------------------------
template <class Key, class Value>
void __fastcall TMapList<Key,Value>::Clear()
{
if (Count > 0)
   {
   if (FOnItemClear)
      {
      for (Iter=Map.begin(); Iter !=Map.end(); ++Iter)
         {
         DoItemClear(Iter->first, Iter->second);
         }
      }

   Map.clear();
   }
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
template <class Key, class Value>
class TPtrMapList : public TMapList<Key, Value>
{
public:
virtual __fastcall ~TPtrMapList(void)
{
this->Clear();
}

virtual void __fastcall Clear()
{
if (!this->Map.empty())
   {
   this->Iter = this->Map.begin();

   for (; this->Iter != this->Map.end(); ++this->Iter)
      {
      if (this->Iter->second != nullptr)
         delete this->Iter->second;
      }
   }

this->Map.clear();
}
};
//---------------------------------------------------------------------------
#endif

As you can see I have 2 TMapList classes one for normal types and another for pointers.
Then I have this code which raises an error when I user a TPtrMapList inside another TMapList like below:

Code: Select all
//Header
struct TTestObject
{
int ID;
String Name;
TStrToStrMap ActionsConditions;
};
typedef TMapList<String,TTestObject*> TTestObjectList;
typedef TMapList<String,TTestObjectList> TResourcesMapList;

class TForm1 : public TForm
{
__published:
...
public:
TResourcesMapList ResourcesMapList;

Code: Select all
void __fastcall TForm1::Btn1Click(TObject *Sender)
{
TTestObjectList ObjectList;
TTestObject* Obj = new TTestObject;

Obj->ID = 1;
Obj->Name = "AAA";

Obj->ActionsConditions.Add("CCC","");

ObjectList.Add("DDD",Obj);

ResourcesMapList.Add("Test", ObjectList); // Error raised here I think the destructor is called but why


I tried using references instead of pointers before but because I am filling the "TTestObjectList" with derived classes from "TTestObject" it was giving me errors as well during casting from base object inside the map to derived class, I tried dynamic_cast, static_cast, reinterpret_cast but nothing works always raises an exception when I use ay new data member from the derived classes.

Now this works fine with shared_ptr instead of using normal pointers but I want to know what am I doing wrong?

I am passing ObjectList as "const reference" shouldn't this pass the same object not make a copy, then why the destructor is called for the TPtrMapList at this point when I add it into another map?

Thanks
User avatar
Emily W. Haley
 
Posts: 1
Joined: Wed May 13, 2020 7:33 pm

Re: map of pointers inside another map raise exception

Postby rlebeau » Mon Jun 08, 2020 2:10 pm

Emily W. Haley wrote:As you can see I have 2 TMapList classes one for normal types and another for pointers.
Then I have this code which raises an error when I user a TPtrMapList inside another TMapList


I just answered this same question in the Embarcadero forum:

https://community.idera.com/developer-t ... 5365#95365
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1683
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA


Return to Technical

Who is online

Users browsing this forum: No registered users and 17 guests

cron