Question

I use a map in my code <BSTR,struct> bstr being the key and struct the value.

Will this work or do I have to redefine something?

I see no compile issues and I'm able to add elements too. However, map.find() does not work. Even though the element is present, it always returns map.end() (element not found).

I did a temporary workaround as follows - by looping from map.begin() to map.end() and doing a lstrcmpW for each element. This seems to work, but dont think this is too efficient.

Any suggestions/tips on what could be wrong? Is it ok to use BSTR as key for a map? I know maps do not support some of the non-native data types - structs or classes...u need to define a < operator for that.

Was it helpful?

Solution

Use ATL's CComBSTR as the key type instead of BSTR. CComBSTR overloads operator< to do actual string comparisson, rather than pointer (address) comparisson as you are currently doing.

CComBSTR also simplifies lifetime management. Using BSTR as the key type, you have to make sure that the BSTRs outlive the lifetime of the map (actually they have to be deallocated right before the map is destructed). CComBSTR follows the RAII principle so you don't have to do any manual deallocation.

OTHER TIPS

BSTR type in C++ is a pointer. Map is comparing the pointers to each other and not the string. To use in map you should probably write a wrapper for BSTR or use a premade wrapper.

Instead of looping from map.begin() to map.end() and doing a lstrcmpW for each element, you can use std::find_if combined with unary_function as follows :

class IsBSTREqual : public unary_function<std::pair<BSTR,int>,bool>
{
private:
    BSTR str;
public:
     IsBSTREqual(BSTR _str)
     {
         str = ::SysAllocString(_str);
     }
     ~IsBSTREqual()
     {
           if(str)
           {
               ::SysFreeString(str);
           }
      }

      bool operator()(const std::pair<BSTR,int> &v)
     {
         if(!lstrcmpW(v.first,str))
         {
             return true;
         }
         return false;
      }
};

BSTR abc = ::SysAllocString(L"String I want to find");
IsBSTREqual _pred(abc);
std::map<BSTR,int>::iterator _it = 
std::find_if(attr_map.begin(),attr_map.end(),_pred);

if(_it != attr_map.end() )
    {
        cout<<"\nFound";
    }
    else
    {
        cout<<"\nNot found";
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top