std::map<,>, xtree and find

I am working on an unmannaged C++ application in Visual Studio 2003.  The application is using STL map class.



std::map<ApxString, CGPO> GPOs;
GPODataFactory.GetGPOs( pContext, GPOs);
std::map<ApxString, CGPO>::iterator GPODataIter = GPOs.find( GPOGroupKey)

 


GPOGroupKey is of type ApxString of course and it was initialized to "T" earlier in the program.

When I go through the debbuger in the GetGPOs function and use the find function, I find the row I am looking for.  However, when I go through the find function after I exit the GetGPOs function, I don't find it.

As I stepped into the find function,



iterator find(const key_type& _Keyval)
{
// find an element in mutable sequence that matches _Keyval
   iterator _Where = lower_bound(_Keyval);
   return (_Where == end() || this->comp(_Keyval, _Key(_Where._Mynode())) end() : _Where);
}

 
 

where the lower_bound function ends up calling the following xtree function



_Nodeptr _Lbound(const key_type& _Keyval) const
{ // find leftmost node not less than _Keyval
   _Nodeptr _Pnode = _Root();
   _Nodeptr _Wherenode = _Myhead;
// end() if search fails
   while (!_Isnil(_Pnode))
      if (this->comp(_Key(_Pnode), _Keyval))
         _Pnode = _Right(_Pnode);
// descend right subtree
      else
      { // _Pnode not less than _Keyval, remember it
         _Wherenode = _Pnode;
         _Pnode = _Left(_Pnode);
// descend left subtree
      }
   return (_Wherenode); // return best remembered candidate
}

 


and this->comp(_Key(_Pnode), _Keyval) calls the following in the functional standard header



// TEMPLATE STRUCT less
template<class _Ty>
struct less
:
public binary_function<_Ty, _Ty, bool>
{
// functor for operator<
   
bool operator()(const _Ty& _Left, const _Ty& _Right) const
   { // apply operator< to operands
      return (_Left < _Right);
   }
};


 


I found that the difference was on the return(_Left < _Right) line.  Although the _Left and _Right values are the same both times ("O" < "T"), I consistently get a true evaluation the first time (which is correct) and false the second time (which is incorrect). This makes no sense.  O is 4F and T is 54 in hex.

Any comments are appreciated.

Thanks in advance,
-stephen




Answer this question

std::map<,>, xtree and find

  • andyr2005

    Write your own compare function:

    struct S_COMPARE_ApxString
    {
    bool operator() (const ApxString  &l, const ApxString  &r) const 
          {
           // Do what ever you need to compare it
    ...
          }
    };

    typedef std::map<ApxString, CGPO, S_COMPARE_ApxString> MYCLASS;



  • vnilo

    Hello Martin,

    Thanks for the response.  That's what I initially thought, but ApxString doesn't have a less than operator.  It is just returning m_pData->m_pchData to the less function in the functional standard header using the following function.



    ApxString::operator const char *() const
    {
       if (m_pData == 0)
       {
          return 0;
       }
       else
       {
          return m_pData->m_pchData;
       }
    }


     


    m_pchData is of type char *.

    Regards,
    -stephen

  • Angie28

    Unless the debbuger is reporting icorrectly, the key value hasn't changed.

    First pass:
    _Left
    {m_pData=0x02220000 {m_pchData=0x02230000 "O" m_dwRefCount=2 m_dwBufferSize=3 } }
        __vfptr: 0x0032a0c0 const ApxString::`vftable'
        m_pData: 0x02220000 {m_pchData=0x02230000 "O" m_dwRefCount=2 m_dwBufferSize=3 }

    _Right
    {m_pData=0x02240000 {m_pchData=0x02250000 "T" m_dwRefCount=3 m_dwBufferSize=3 } }
        __vfptr: 0x0032a0c0 const ApxString::`vftable'
        m_pData: 0x02240000 {m_pchData=0x02250000 "T" m_dwRefCount=3 m_dwBufferSize=3 }

    Second pass:
    _Left
    {m_pData=0x02220000 {m_pchData=0x02230000 "O" m_dwRefCount=2 m_dwBufferSize=3 } }
        __vfptr: 0x0032a0c0 const ApxString::`vftable'
        m_pData: 0x02220000 {m_pchData=0x02230000 "O" m_dwRefCount=2 m_dwBufferSize=3 }
    _Right
    {m_pData=0x021b0000 {m_pchData=0x021e0000 "T" m_dwRefCount=4 m_dwBufferSize=3 } }
        __vfptr: 0x0032a0c0 const ApxString::`vftable'
        m_pData: 0x021b0000 {m_pchData=0x021e0000 "T" m_dwRefCount=4 m_dwBufferSize=3 }

    Thanks,
    -stephen

  • Frosty1_4me

    Sounds good. Thanks for the help Martin.



  • GradyMeng

    Is there a chance that you operator< for ApxString doesn't work correct.

  • James Downey

    Well, Martin, you're right.  The < operator is not working correctly with ApxString.  If I do

    ApxString key1 = "A";
    ApxString key2 = "B";

    if (key1 < key2)
    {
       ...
    }

    It doesn't use the value of the string but the memory address of the m_pchData which is weird because if I step into the if statement, it shows that it is returning m_pData->m_pchData from ApxString::operator const char *() const

    I contacted the developer of ApxString but any help is appreciated.

    thanks,
    -stephen 

  • ZaDDaZ

    But is there a chance that in the lifetime this value changes In this case you get problems. The key value must be persistent!

  • std::map<,>, xtree and find