Hi,

I am trying to develop one requirement wherein I need a C++ map having both Key and Value as Structures.

The structures are as follows:

typedef struct _keyInfo
{
int Key1; 
int Key2; 
} T_KeyInfo, * T_pKeyInfo;

typedef struct _valueInfo
{ 
int value1; 
int value2; 
int value3; 
} T_ValueInfo, * T_pValueInfo;

and my map is:

typedef map<T_pKeyInfo, T_pValueInfo> T_Map, * T_pMap;

I tried to insert one row into this map using the insert command:

M_pMap->insert(T_Map::value_type(L_pKey,L_pValue));

and Later I am trying to retrive the stored values in the map using find command

T_Map::iterator L_iterator;
T_pKeyInfo L_pKey = NULL;
T_pValueInfo L_pValue = NULL;

L_iterator = M_pMap->find(T_Map::key_type(L_pKey));
if (L_iterator != M_pMap->end())
{
L_pValue = L_iterator->second;
int P_Result=L_pValue->value1;
}

Somehow I am not able to retrive the value1 from the map using the above code.

Can anyone please help me in resolving this issue.
It will be OK, if any better approach/procedure exists to have a map with key and value as structs.

Thanks in advance...............


karthik

Ok you have (a) made a few basic errors (b) confused how map searches work and (c) made it very very difficult to read by using C like layout and constructs.

I will address (c) first by writing some c++ like code (others may object but I think it is better than your attempt :)

#include <iostream>
#include <map>

struct keyInfo
{
  int Key1; 
  int Key2; 

  keyInfo(const int A,const int B) : 
    Key1(A),Key2(B) {}

  bool operator<(const keyInfo& A) const
    { return Key1<A.Key1; }
};

struct valueInfo
{ 
  int value1; 
  int value2; 
  int value3; 

  valueInfo(const int A,const int B,const int C) : 
    value1(A),value2(B),value3(C) {}
};

typedef std::map<keyInfo, valueInfo> MapTYPE;
typedef std::map<keyInfo*, valueInfo*> MapPTYPE;


int
main()
{
  MapTYPE TMap;
  MapPTYPE PMap;

  keyInfo A(1,2);  
  valueInfo B(1,2,3);

  TMap.insert(MapTYPE::value_type(A,B));
  PMap.insert(MapPTYPE::value_type(&A,&B));
  MapPTYPE::iterator mIter=PMap.find(&A);
  if (mc!=PMap.end())
      std::cout<<"Success"<<std::endl;

  MapTYPE::iterator vIter=TMap.find(MapTYPE::key_type(1,2));
   if (vc!=TMap.end())
     {
       std::cout<<"Second Success"<<std::endl;
       std::cout<<vIter->second.value3<<std::endl;
     }

As you will see I have dropped your naming convension, sorry, but I hate hungarian notation.

So what have I done. First off I have added a simple constructor for both classes. You don't need them but they keep me happy!

Second I have created both types of map , one that stores pointers to the key value and one that stores the key value. There are not that many cases when you would want to store key pointer but they exist.

Next AND VERY important. map requires that there is a less comparitor. The default is std::less, which falls back to operator< if you define one for your class. I have done that. You can write your own and add it in. If you are using pointers, I would strongly recomend that. Because otherwize you need exact pointer matching.

Using the one that I have defined in your struct is ok and works.

In your struct, you search for a pointer of value NULL. Since you did not add any key with that pointer value, the program correctly works by giving you the end() iterator. In my example I have added a pointer to A, and I search for the same memory address. This works.

This is a forum, so please feel free to post further examples, and construct a dialog.

Sorry, kbshibukumar, I am going to be a little picky :) , you do not have to implement the operator< in teh key struct. Consider the code below:

#include <iostream>
#include <map>

struct valueInfo
{ 
  int value1; 
  int value2; 
  int value3; 

  valueInfo(const int A,const int B,const int C) : 
    value1(A),value2(B),value3(C) {}
};

class valueComp 
{
public:

  bool operator()(const valueInfo& A,
		  const valueInfo& B)
    const
    { return A.value2<B.value2; }
};

typedef std::map<valueInfo,double,valueComp> MapCTYPE;

int
main()
{
  MapCTYPE TMap;

  valueInfo B(1,2,3);
  valueInfo C(3,3,4);

  TMap.insert(MapCTYPE::value_type(B,4.5));
  TMap.insert(MapCTYPE::value_type(C,8.4));

  MapCTYPE::iterator vc=TMap.find(MapCTYPE::key_type(1,2,8));
  if (vc!=TMap.end())
    {
      std::cout<<"Success:"<<vc->second<<std::endl;
    }
}

What I have done there is add an external less comparitor. This prevents having to pollute the class with an inappropiate operator< and allows several different comparitors in different maps/vectors.

Of course this will work. However, what is the need of a separate class just to implement the < operator. Does it have any more advantage than implementing in the struct itself?

There are basic two instances that require a separate funtion.
(a) when you want different sorting characteristics (b) when you want to store state for the sort.

Let us consider some examples:

A set of points in 3D. (i) Sorting all the points that are closest to another fixed point. (ii) Sorting all the points are closest to a line.
Both of these sorts have "state" to be preserved (ie the datum point/line). Finally, you will find both of these sorts (and others) in almost any molecular simulation [although the 3D point will be replaced with 3D atom].

Hi StuXYZ and kbshibukumar,

Thanks alot for sharing the valuable info to me.

Sorry for being out of context for some time.

The provided example in the previous discussion helped me alot in resolving my problem.

I need some more help related to the less comparator of the map. Sorry I am bit less knowledgeable on this topic.

Now I am having a structure "keyInfo"as a key having two different Key1 and Key2 fields.

struct keyInfo{  
int Key1;   
int Key2;    

keyInfo(const int A,const int B) :     
Key1(A),Key2(B) {}   

bool operator<(const keyInfo& A) const    
{ return Key1<A.Key1; }};

For me, the individual key values Key1 and Key2 can have duplicates as well, but the combination of both should result in a unique row.

For example:  key1   Key2      Value1    Value2    Value3
              0        1           1            2            3  
                          1     1           4           5             6
              2         1           7           8            9
              1         4          10          11           12

As you can see from the above example, the combination of Key1 and Key2 are unique.

For this requirement, I modified the above comparator as below

struct keyInfo{  
int Key1;   
int Key2;    

keyInfo(const int A,const int B) :     
Key1(A),Key2(B) {}   

bool operator<(const keyInfo& A) const    
{return ((Key1==keyInfo.Key1) && (Key2==keyInfo.Key2)); }

I have no clue why this comparision is failing in retriving.....

Please guide me in resolving this poblem.

Thanks in advance.

Edited 3 Years Ago by mike_2000_17: Fixed formatting

Posting the example part again....

For example: key1 Key2 Value1 Value2 Value3
0 1 1 2 3
1 1 4 5 6
2 1 7 8 9
1 4 10 11 12

I realize this is a dated question but, didn't want to leave it hanging.

bool operator<(const keyInfo& A) const
    {
        return ((Key1<A.Key1) || (Key2<A.Key2));
    }

Edited 3 Years Ago by Nick Evan: Fixed formatting

This article has been dead for over six months. Start a new discussion instead.