Microsoft KB Archive/114833

{|
 * width="100%"|

FIX: Error C2664 Generated with Class Created by TEMPLDEF

 * }

Q114833

-

The information in this article applies to:


 * The Microsoft Foundation Classes (MFC), included with:
 * Microsoft Visual C++, versions 1.0, 1.5

-

SYMPTOMS
When a user-defined MFC collection class of the form

  CMap 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 MaptoString 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)); ConstructElement(&pAssoc->value); memset(&pAssoc->value, 0, sizeof(VALUE)); 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 CMaptoString because key is declared as WORD and ConstructElement expects a CString*.
 * 1) if HAS_CREATE
 * 1) else
 * 1) endif

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 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

Issue type :

Technology : kbAudDeveloper kbMFC