Reputation: 5933
I'm currently working on a DLL that needs to convert back and forth between the friendly name for a value and the value itself. As this code is used in many places throughout the codebase, I want to try and keep it simple and in a single function or object so I only have to declare them once.
From my reading it looks like CMap
is the tool for the job, but I can't seem to discover any combination of template arguments that compiles without errors.
My values are CString
and int
. I tried the following definition:
CMap<int, int, CString, CString> encodermap;
which compiles, but when I try to add a value:
encodermap["Encoder 1"] = 0;
I get the following compiler errors:
error C2057: expected constant expression
error C2466: cannot allocate an array of constant size 0
error C2501: 'encodermap' : missing storage-class or type specifiers
error C2040: 'encodermap' : 'int []' differs in levels of indirection from 'CMap<KEY,ARG_KEY,VALUE,ARG_VALUE>'
I've tried changing the CMap
to this:
CMap<CString, CString, int, int> encodermap;
but I get the same four errors.
I'm sure I must be missing something but I'm at a loss as to what.
Because of the SDK being used for this work I'm require VS2003
Upvotes: 3
Views: 9599
Reputation: 382
Try this:
CMap<CString, LPCTSTR, int, int> encodermap;
This CodeProject article CMap How-to may be of some help.
Many people get confused about CMap's declaration
CMap < KEY, ARG_KEY, VALUE, ARG_VALUE >
, why not justCMap < KEY, VALUE >
?In fact, the ultimate data container in
CMap
isCPair
, and the internal ofCPair
is{KEY, VALUE}
. Therefore,CMap
will really store aKEY
, and notARG_KEY
. However, if you check with the MFC source code, almost all the internal parameters passing withinCMap
itself is called withARG_KEY
andARG_VALUE
, therefore, usingKEY &
asARG_KEY
seems always a correct thing, except when:
- You are using primitive date types like
int
,char
, where pass-by-value makes no difference (may be even faster) with pass-by-reference.- If you use
CString
asKEY
, you should useLPCTSTR
asARG_KEY
and notCString &
, we will talk more about this later.
Edit: Cristophe, another option for the assignment is encodermap[_T("Encoder 1")] = 0;
, which will work for single-byte, multi-byte or Unicode with the LPCTSTR
typedef. You will also need to #include <tchar.h>
.
Upvotes: 3
Reputation: 73446
The problem
I think you've inverted the key type and the valye type.
Your original declaration defines int
as being the key to be searched for with operator[]
. So encodermap[0] = "Encoder 1";
would work.
But when your compiler sees encodermap["Encoder 1"] = 0;
, he tries to find an operator[]
which takes char* (or something to which char * can be converted to) and returns an int. The last error message tells you that he couldn't find such an operator for your map.
With MSVC 2015, the error message is more concise: C2679.
The solution
You should define your CMap
with a CString
key and an int
value. The trick to know, is that for a CString
KEY, the the ARG_KEY should be LPCWSTR
. So the right definition would be:
CMap<CString, LPCWSTR, int, int> encodermap;
This permits to use CString
as key in the map's operator[]
.
Now if you use MFC on windows, you probably use UNICODE and wide chars (therefore the LPCWSTR instead of LPCSTR). When calling the operator you then have either to use a CString or a wide literal:
encodermap[L"Encoder 1"] = 0;
encodermap[CString("Encoder 2")] = 1;
Upvotes: 6