FIX: Error C2664 Generated with Class Created by TEMPLDEF

ID: Q114833


The information in this article applies to:


SYMPTOMS

When a user-defined MFC collection class of the form


   CMap<any type>toString 
is generated using the TEMPLDEF utility and when the class is compiled with /AS or /AM, for small or medium memory model, the compiler generates the following error message:
error C2664: 'ConstructElement' : cannot convert parameter 1 from

'unsigned short __near *' to 'class ::CString __near *'
If the code was compiled with /AL or /AC, for large or compact memory model, the error message contains __far instead of __near, because in these memory models, pointers are far pointers by default.


CAUSE

The TEMPLDEF utility is passed several parameters to create a new collection class. One of these is HAS_CREATE. The following code is inserted into the newly created class code if HAS_CREATE is defined:


        ASSERT(m_nCount > 0);  // make sure we don't overflow
        memset(&pAssoc->key, 0, sizeof(KEY));
        ConstructElement(&pAssoc->key);  // special construct values 
When creating a Map<Type>toString class, HAS_CREATE is defined. The ConstructElement() function is only used with CStrings and is defined in the header file ELEMENTS.H. Creating a CMapWordtoString class would use the MAP.CTT template. The code listed above is from the MAP.CTT template.

The only class that maps from CStrings is CMapStringToString. This class is expanded from MAP_S.CTT. The code from MAP_S.CTT is:

        ASSERT(m_nCount > 0);  // make sure we don't overflow
        memcpy(&pAssoc->key, &afxEmptyString, sizeof(CString));
#if HAS_CREATE
        ConstructElement(&pAssoc->value);
#else
        memset(&pAssoc->value, 0, sizeof(VALUE));
#endif 
Notice that the ConstructElement() parameter in MAP_S.CTT is the value member of pAssoc if HAS_CREATE is defined (instead of the key member as listed in MAP.CTT). Passing key to ConstructElement() is sure to fail in the case of CMap<TYPE>toString because key is declared as WORD and ConstructElement() expects a CString*.


RESOLUTION

Change the source file containing the call to ConstructElement() so that it is passed the value field of pAssoc. It should look like:


   ConstructElement(&pAssoc->value); 


STATUS

Microsoft has confirmed this to be a bug in the Microsoft Foundation Classes, versions 2.0 and 2.5. This problem was corrected in MFC version 3.0, included with Visual C++ version 2.0.


MORE INFORMATION

In order to reproduce the problem, copy all of the following lines to MKCOLL.BAT:


   templdef "CMap<WORD, WORD, CString, const char*,1,1> CMapWordtoString"
   map.ctt temp.h temp.inl map_ws.cpp
   copy newcoll.h+temp.h newcoll.h
   copy newcoll.inl+temp.inl newcoll.inl 

Additional query words: 1.00 1.50 2.00 2.50


Keywords          : kb16bitonly kbnokeyword kbMFC kbVC 
Version           : 1.00 1.50
Platform          : WINDOWS 
Issue type        : 

Last Reviewed: July 20, 1999