Solved

ATL and <map>

Posted on 2001-06-15
13
211 Views
Last Modified: 2013-12-14
Ive got problems trying to build a map<_TCHAR *, _TCHAR *>

First, I'll write my code:
     typedef map<_TCHAR *, _TCHAR *> type_Data;
     typedef type_Data::value_type vtItem;
   
      type_Data object;
      type_Data::iterator it;

if i build the map using variables, that is:
_TCHAR object_insert1[]="Item 1";
_TCHAR object_insert2[]="Item 2";
_TCHAR object_insert3[]="Item 3";
_TCHAR object_insert4[]="Item 4";
object.insert(vtItem(object_insert1,_T("VALUE_1")));
object.insert(vtItem(object_insert2,_T("VALUE_2")));
object.insert(vtItem(object_insert3,_T("VALUE_3")));
object.insert(vtItem(object_insert4,_T("VALUE_4")));

and i try to find an item using another variable,

_TCHAR object_find[]="Item 2";
it = object.find(object_find);

it doesn't find anything;

But if i build the map using strings without variables, that is:

object.insert(vtItem(_T("Item 1"),_T("VALUE_1")));
object.insert(vtItem(_T("Item 2"),_T("VALUE_2")));
object.insert(vtItem(_T("Item 3"),_T("VALUE_3")));
object.insert(vtItem(_T("Item 4"),_T("VALUE_4")));

 I find any of the items i'm looking for.

Does anyone know what's the problem?
0
Comment
Question by:Moony
  • 7
  • 5
13 Comments
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6194739
The problem is that you are storing pointers in the map, so the test made using find will do pointer comparison, hence typically, you will not find them.

You need something like this:

struct tstr_equal
{
  TSTR* mValue;
  tstr_equal(TSTR* s) : mValue(s) {}
  bool operator()(pair<const K, V> elem)
  {
     return wcscmp( elem->second, mValue ) == 0;
     // or however you compare TSTRs...
  }
};


then

it = find_if(object.begin(), object.end(),
             tstr_equal(object_find));

0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6195293
try typing your map

typedef map<string, string> type_Data;
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6195394
> try typing your map
> typedef map<string, string> type_Data;

wouldn't be very useful if unicode strings were being stored.
0
The Eight Noble Truths of Backup and Recovery

How can IT departments tackle the challenges of a Big Data world? This white paper provides a roadmap to success and helps companies ensure that all their data is safe and secure, no matter if it resides on-premise with physical or virtual machines or in the cloud.

 
LVL 9

Accepted Solution

by:
jasonclarke earned 200 total points
ID: 6195446
There were a few mistakes in the code I presented earlier, but here is a complete example that demonstrates the technique:

#pragma warning(disable:4786)

#include <tchar.h>
#include <map>
#include <algorithm>

using namespace std;

struct tstr_equal
{
 _TCHAR* mValue;

 tstr_equal(_TCHAR* s) : mValue(s) {}

 bool operator()(pair<_TCHAR *, _TCHAR *> elem)
 {
    return _tcscmp( elem.first, mValue ) == 0;
 }
};

int main()
{
    typedef map<_TCHAR *, _TCHAR *> type_Data;
    typedef type_Data::value_type vtItem;
   
    type_Data object;
    type_Data::iterator it;

    _TCHAR object_insert1[]="Item 1";
    _TCHAR object_insert2[]="Item 2";
    _TCHAR object_insert3[]="Item 3";
    _TCHAR object_insert4[]="Item 4";
    object.insert(vtItem(object_insert1,_T("VALUE_1")));
    object.insert(vtItem(object_insert2,_T("VALUE_2")));
    object.insert(vtItem(object_insert3,_T("VALUE_3")));
    object.insert(vtItem(object_insert4,_T("VALUE_4")));

    _TCHAR object_find[]="Item 2";
    it = find_if(object.begin(), object.end(), tstr_equal(object_find));

    _TCHAR* key = it->first;
    _TCHAR* value = it->second;

    return 0;
}
0
 

Author Comment

by:Moony
ID: 6195824
Wow! Your answer was perfect! Thank you very much!
0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6195982
> wouldn't be very useful if unicode strings were being stored.

#ifdef _UNICODE
#define wstring string
#endif

no problem
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6201461
> no problem

maybe, maybe not.  Many programs do not have the luxury of being able to operate entirely in one character set or another.  This kind of #define makes it impossible to use string for its plain ASCII text usage.
0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6201639
picky picky

typedef map<wstring, wstring> type_Data;

now we handle unicode strings

0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6201702
> typedef map<wstring, wstring> type_Data;

still not really good enough, since the problem with TCHAR is that you don't know whether it will be wide until run-time, so you would have to do something like:

#ifdef _UNICODE
    typedef map<wstring, wstring> type_Data;
#else
    typedef map<string, string> type_Data;
#endif

Which, I agree does make life somewhat simpler.  Using pointers is probably more troublesome in general.  

But, having said that, it is possible to store TCHAR pointers directly in the map.  The use is just a bit more complicated, and somewhat less efficient.
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6201707
> whether it will be wide until run-time

I meant compile time rather than run time....
0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6201718
typedef basic_string<wchar_t> wstring;

and as I understand it wchar_t is a 'unsigned short' (see stddef.h) so by using wstring you know it is a wide string (unicode) - and since you solution used TCHAR then the same could be said about your own proposed solution
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6201752
> and since you solution used TCHAR

not sure I understand your comment...

but the actual type of TCHAR depends on the system settings, i.e. if UNICODE, TCHAR = wchar_t, otherwise TCHAR = char.  

An advantage of using TCHARs directly is that maybe it makes it obvious that conversion *MAY* always be needed, it might be less easy to forget to do the conversion.
0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6202271
typedef basic_string<TCHAR> tstring;

its really not hard to apply the stl templates

0

Featured Post

Microsoft Certification Exam 74-409

Veeam® is happy to provide the Microsoft community with a study guide prepared by MVP and MCT, Orin Thomas. This guide will take you through each of the exam objectives, helping you to prepare for and pass the examination.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
C++ Language error 28 218
Eclipse Neon and jdk 1.8.0 11 201
WPF issue with Trigger 2 106
No module found pypyodbc, 3 16
Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Jaspersoft Studio is a plugin for Eclipse that lets you create reports from a datasource.  In this article, we'll go over creating a report from a default template and setting up a datasource that connects to your database.
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question